【Tkinter】複数の画面(フレーム)をボタン操作で切り替えて表示させる【画面遷移(tkraise)】

時計 2020.12.06 / 時計

【Tkinter】複数の画面(フレーム)をボタン操作で切り替えて表示させる【画面遷移(tkraise)】

私は社内で使用するためのデスクトップアプリケーションをよく開発しています。
社内業務の効率化には、その業務に合ったデスクトップアプリケーションを開発するのが簡単ですからね。

デスクトップアプリケーションの使い勝手をよくするために、複数のウィンドウを表示するのではなく、1つのウィンドウで様々な操作ができるようにしています。

そのために1つのウィンドウで複数の画面(フレーム)切り替えて表示できるようにしています。

私がGUIアプリケーション開発で使用しているのはPythonのTkinterです。

本記事では、Tkinterによる複数の画面(フレーム)をボタン操作で切り替えて表示させる(画面遷移)方法を解説していきます。

Tkinterによる画面遷移の方法

Tkinterで作成するGUIアプリで画面遷移を実現するには2つの方法が考えられます。

  • 表示しているFrame(フレーム)を削除して、新しいFrameを作成する
  • メインウィンドウに複数のFrameを重ね、表示したいFrameを最前面に移動させる

1番はFrame(フレーム)を削除しているので、厳密に画面遷移とは言えませんが、見た目では画面が切り替わったように感じます。

2番は複数のFrameを切り替えて表示しているので、実際にアプリ開発をする場合はこの方法をしようしています。

Frame削除で画面切り替え

Frameの削除方法(delete()メソッド)

前述しているように、表示しているFrame(フレーム)を削除し、新しいFrameを表示することで画面が切り替わったように見せる方法です。

Frameを削除の図解

Frameの削除には、削除したいFrameに対してdestroy()メソッドを使用します。

    frame.destroy()

サンプルプログラム

以下にFrameを削除して画面切り替えをしているように見せているTkinterアプリのプログラムソースを記します。

# tkinterのインポート
import tkinter as tk
import tkinter.ttk as ttk

def make():
    global frame

    frame_app.destroy()

    # メインフレームの作成と設置
    frame = ttk.Frame(root)
    frame.pack(fill = tk.BOTH, pady=20)

    # 各種ウィジェットの作成
    label1_frame = ttk.Label(frame, text="メインウィンドウ")
    entry1_frame = ttk.Entry(frame)
    button_change = ttk.Button(frame, text="ウィンドウ変更", command=change)

    # 各種ウィジェットの設置
    label1_frame.pack()
    entry1_frame.pack()
    button_change.pack()


def change():
    global frame_app

    frame.destroy()

    # メインフレームの作成と設置
    frame_app = ttk.Frame(root)
    frame_app.pack(fill = tk.BOTH, pady=20)

    # 各種ウィジェットの作成
    label1_frame_app = ttk.Label(frame_app, text="アプリウィンドウ")
    entry1_frame_app = ttk.Entry(frame_app)
    button_change_frame_app = ttk.Button(frame_app, text="ウィンドウ戻す", command=make)

    # 各種ウィジェットの設置
    label1_frame_app.pack()
    entry1_frame_app.pack()
    button_change_frame_app.pack()

if __name__ == "__main__":
    # rootメインウィンドウの設定
    root = tk.Tk()
    root.title("tkinter application")
    root.geometry("300x150")

    # メインフレームの作成と設置
    frame = ttk.Frame(root)
    frame.pack(fill = tk.BOTH, pady=20)

    # 各種ウィジェットの作成
    label1_frame = ttk.Label(frame, text="メインウィンドウ")
    entry1_frame = ttk.Entry(frame)
    button_change = ttk.Button(frame, text="ウィンドウ変更", command=change)

    # 各種ウィジェットの設置
    label1_frame.pack()
    entry1_frame.pack()
    button_change.pack()

    root.mainloop()

このアプリを起動し、画面遷移ボタンを押すと以下のように画面は切り替わります。

画面遷移の画像の切り替わり

上記の画像からもわかるように、Frameを削除して新しいFrameを作成・表示するため、入力欄に入れた値は画面切り替え後には、空になってしまいます。

表示したいFrameを最前面に移動

最前面に移動する方法(tkraise()メソッド)

次に紹介する方法は、複数のFrame(フレーム)を1つのメインウィンドウに重ねて設置する方法です。

ウィンドウにFrameを重ねて設置している図解

表示したいFrameはtkraise()メソッドを使用して、最前面に移動させます。
tkraise()メソッドは対象のFrameを最前面に移動させます。

    frame.tkraise()

重ねる各Frameはgrid()メソッドで座標(0, 0)に設置します。
また引数にsticky="nsew"を入れて、メインウィンドウと同じサイズにしておくことも必要です。

    frame.grid(row=0, column=0, sticky="nsew")

メインウィンドウのグリッド数を1×1にしておくと、Frameの配置がズレなくなります。

    root.grid_rowconfigure(0, weight=1)
    root.grid_columnconfigure(0, weight=1)

サンプルプログラム

以下に複数のFrame表示を切り替えるTkinterプログラムのソースを記します。

# tkinterのインポート
import tkinter as tk
import tkinter.ttk as ttk

def change_app():
    frame_app.tkraise()

def change_main():
    frame.tkraise()

if __name__ == "__main__":
    # rootメインウィンドウの設定
    root = tk.Tk()
    root.title("tkinter application")
    root.geometry("300x150")

    # rootメインウィンドウのグリッドを 1x1 にする
    root.grid_rowconfigure(0, weight=1)
    root.grid_columnconfigure(0, weight=1)


    # メインフレームの作成と設置
    frame = ttk.Frame(root)
    frame.grid(row=0, column=0, sticky="nsew", pady=20)

    # 各種ウィジェットの作成
    label1_frame = ttk.Label(frame, text="メインウィンドウ")
    entry1_frame = ttk.Entry(frame)
    button_change = ttk.Button(frame, text="アプリウィンドウに移動", command=change_app)

    # 各種ウィジェットの設置
    label1_frame.pack()
    entry1_frame.pack()
    button_change.pack()

    # アプリフレームの作成と設置
    frame_app = ttk.Frame(root)
    frame_app.grid(row=0, column=0, sticky="nsew", pady=20)

    # 各種ウィジェットの作成
    label1_frame_app = ttk.Label(frame_app, text="アプリウィンドウ")
    entry1_frame_app = ttk.Entry(frame_app)
    button_change_frame_app = ttk.Button(frame_app, text="メインウィンドウに移動", command=change_main)

    # 各種ウィジェットの設置
    label1_frame_app.pack()
    entry1_frame_app.pack()
    button_change_frame_app.pack()

    # frameを前面にする
    frame.tkraise()

    root.mainloop()

このアプリを起動し、画面遷移ボタンを押すと以下のように画面は切り替わります。

tkraise()メソッドによる画面遷移の流れ

「Frame削除で画面切り替え」プログラムとは異なり、入力欄に入れた値は空にならずにそのまま残っています。

lambda(ラムダ式)で書き換え

lambda(ラムダ式)を使用して、アプリの拡張がしやすいようにしてみます。

今のままでは、重ねるFrameの数だけ関数を作成する必要があります。
これをlambda(ラムダ式)を使用して、一つの関数で複数のFrameに対応できるようにします。

# tkinterのインポート
import tkinter as tk
import tkinter.ttk as ttk

def change_app(window):
    window.tkraise()

if __name__ == "__main__":
    # rootメインウィンドウの設定
    root = tk.Tk()
    root.title("tkinter application")
    root.geometry("300x150")
    …
    # 各種ウィジェットの作成
    label1_frame = ttk.Label(frame, text="メインウィンドウ")
    entry1_frame = ttk.Entry(frame)
    button_change = ttk.Button(frame, text="アプリウィンドウに移動", command=lambda: change_app(frame_app))
    …
    # 各種ウィジェットの作成
    label1_frame_app = ttk.Label(frame_app, text="アプリウィンドウ")
    entry1_frame_app = ttk.Entry(frame_app)
    button_change_frame_app = ttk.Button(frame_app, text="メインウィンドウに移動", command=lambda: change_app(frame))
    …
    # frameを前面にする
    frame.tkraise()
    root.mainloop()

ボタンウィジェットのcommandに対してlambdaを使い、関数の引数に表示したいFrameを与えています。

change_app関数では、引数で受け取ったFrame値をtkraise()メソッドで最前面に表示します。

まとめ

Tkinterによる複数の画面(フレーム)をボタン操作で切り替えて表示させる方法はいかがでしたか。

今回紹介した方法は、アプリを作成する上で非常に有用な技術です。

あまりネットにはtkraise()メソッドについて記載している記事は少ないですが、ぜひ使ってみてください。