Tkinterでメモアプリを開発する (2) - テキストファイルにメモを保存する

シリーズ - Tkinterでメモアプリを開発する

今回は、前回作成したHello Worldプログラムを参考にして、早速メモ帳アプリを開発していきます。

今回はメモ帳アプリに以下の機能を追加することにします。

  1. メモを記述するテキストボックスを配置する。
  2. Control+Sでテキストボックスの内容をファイルに保存する。
  3. アプリ起動時にそのファイルの内容をテキストボックスに表示する。

それでは早速メモ帳アプリを開発していきます。
まずは前回のプログラムを参考に、ルートウィンドウを作成してその中にフレームを配置、
フレーム内にテキストボックスを配置するところまで進めます。

Tkinterでは主にEntryTextの2種類のウィジェットがテキストボックスの役割を担っています。
Entryウィジェットは一行のテキスト入力を受け付けるために使用され、
Textウィジェットは複数行のテキストの入力を受け付けることが可能です。
そのため、今回はTextウィジェットを使用します。

from tkinter import Tk, Text
from tkinter import ttk


# ルートウィンドウを作成
root = Tk()

# フレームを配置
frm = ttk.Frame(root, padding=10)
frm.grid()

# テキストボックスをフレーム内に配置
text_widget = Text(frm)
text_widget.grid(column=0, row=0)

# メインループ実行
root.mainloop()

上記コードを実行すると、以下のウィンドウが表示されました。

フレームのpadding=10でルートウィンドウとの間の余白サイズを指定しているため、
このサイズをもう少し小さくしてみます。

...
# フレームを配置
frm = ttk.Frame(root, padding=5)
frm.grid()
...

次に、ウィンドウ上でCtrlキーとSキーを同時に押した際に、
ファイルにTextの内容が保存されるように設定します。

テキストウィジェット内のテキストはgetメソッドを使用して取得できます。

text_widget.get(<開始位置>, <終了位置>)

位置情報は "<行数>.<文字のインデックス>" のようにして指定します。
そのため、最初の文字を指定する場合は、 "1.0" (1行目の0番目の文字)となります。
また、文末は"end"として指定できます。

よって、全文を取得するには以下のように指定します。

text = text_widget.get("1.0", "end")

キーバインドの設定はウィジェットのbindメソッドを使用します。
今回はアプリ上のどこでもControl+sで保存できるようにしたいため、rootにキーバインドを設定します。

# Control+S でテキストを保存する
root.bind('<Control-s>', <実行する関数>)

上記設定を行うと、Control+sが入力された際にイベント(event)を引数として関数が実行されます。

最後に、今までの内容をまとめて、データをファイルに保存する関数を定義します。

from pathlib import Path

# メモを保存するファイル (スクリプトと同じディレクトリに作成する)
MEMO_FILE = Path(__file__).parent / "memo.txt"


def save_text(event=None):
    """text_widgetの内容をファイルに保存する."""
    text = text_widget.get("1.0", "end")
    with open(MEMO_FILE, "w") as f:
        f.write(text)

では、ここまでに作成した以下のコードを実行してみましょう。

from tkinter import Tk, Text
from tkinter import ttk
from pathlib import Path


# メモを保存するファイル
# (スクリプトと同じディレクトリに作成する)
MEMO_FILE = Path(__file__).parent / "memo.txt"

# ルートウィンドウを作成
root = Tk()

# フレームを配置
frm = ttk.Frame(root, padding=5)
frm.grid()

# テキストボックスをフレーム内に配置
text_widget = Text(frm)
text_widget.grid(column=0, row=0)

def save_text(event=None):
    """text_widgetの内容をファイルに保存する."""
    text = text_widget.get("1.0", "end")
    with open(MEMO_FILE, "w") as f:
        f.write(text)

# Control+S でテキストを保存する
root.bind('<Control-s>', save_text)

# メインループ実行
root.mainloop()

テキストウィジェット内に適当な文字列を入力してControl+sを入力すると、
スクリプトと同じディレクトリにmemo.txtが作成され、その中にデータが保存されているはずです。

最後に、アプリ起動時にメモファイルの内容をテキストウィジェットに最初に表示させるように設定します。
テキストウィジェットへの入力はinsertメソッドを使用します。

def load_text():
    """起動時にファイルの内容をテキストボックスに読み込む."""
    if MEMO_FILE.exists():
        with open(MEMO_FILE, "r") as f:
            text = f.read()
            text_widget.insert("1.0", text)  # 最初の位置にtextを挿入する

この関数をメインループ前に実行するように設定します。
最終的なコードは以下になります。

from tkinter import Tk, Text
from tkinter import ttk
from pathlib import Path


# メモを保存するファイル
# (スクリプトと同じディレクトリに作成する)
MEMO_FILE = Path(__file__).parent / "memo.txt"

# ルートウィンドウを作成
root = Tk()

# フレームを配置
frm = ttk.Frame(root, padding=5)
frm.grid()

# テキストボックスをフレーム内に配置
text_widget = Text(frm)
text_widget.grid(column=0, row=0)

def load_text():
    """起動時にファイルの内容をテキストボックスに読み込む."""
    if MEMO_FILE.exists():
        with open(MEMO_FILE, "r") as f:
            text = f.read()
            text_widget.insert("1.0", text)

def save_text(event=None):
    """text_widgetの内容をファイルに保存する."""
    text = text_widget.get("1.0", "end")
    with open(MEMO_FILE, "w") as f:
        f.write(text)

# Control+S でテキストを保存する
root.bind('<Control-s>', save_text)

# テキストウィジェットの内容を初期化
load_text()

# メインループ実行
root.mainloop()

今回はテキストボックスを配置して入力したデータをファイルに保存する簡単なメモ帳アプリを作成しました。
次回は複数のメモを作成・閲覧できるように調整を行います。

関連記事