Tkinterの階層構造とフレーム(Frame)

Tkinterの階層構造とフレーム(Frame)ウィジェット

Tkinterでウィジェットを作成・配置する際の階層構造の構成と、そのために使用するフレーム(Frame)ウィジェットについて解説します。あるべき構造を理解してから作り始めることで効率的な運用が見込めます。

目次

TkinterにおけるWidgetの階層構造

Tkinterではウィジェットは階層構造を構成するように作成します。

root要素にそのまま各ウィジェットを配置していくこともできますが、フレームで各ウィジェットをまとめてグループ化することでプログラムをフレーム単位でモジュール化することができ、フレームを乗せ換えることでアプリケーションの画面を切り替えることもできるようになります。

GUI画面では次のように表示されます。

フレーム(Frame)ウィジェットとは

フレーム自体はほとんど何をするわけでもありませんが、他のウィジェットをまとめて配置するためのコンテナとして働きます。

Frameインスタンスを作成する際は次のようなオプション引数を指定することができます。

属性 説明
bg or background 背景の色を指定します red,blue,grayなど
bd or borderwidth ボーダーの幅を指定します ピクセル単位の数値
relief ボーダー部分の浮き彫りを指定します flat,raised,sunken,groove,ridge
width 幅をピクセル単位で指定します ピクセル単位の数値
height 高さをピクセル単位で指定します ピクセル単位の数値

Frame を作成する際は親ウィジェット(今回はルート要素)を指定します。

import tkinter as tk

root = tk.Tk()

# ウィンドウの設定
root.title("ウィンドウのタイトル")
root.geometry("400x300")

# フレームの作成
frame1 = tk.Frame( # frame1インスタンスを作成
    root, # root要素であるウィンドウを指定
    background="gray", # 背景色を指定
    borderwidth=5, # ボーダーの幅を指定
    relief="sunken", # ボーダーの浮き彫りを指定
    width=400, # 幅をpixel単位で指定
    height=300, # 高さをpixel単位で指定
    )
frame1.pack() # frame1インスタンスを配置

root.mainloop() # イベントハンドラの呼び出し

上記のようなウィンドウが表示されます。

実際の例としてFrameウィジェットの中にLabel、Entry、Buttonを配置してみましょう。

先ほどのように手続き型で書いていくこともできますが、Tkinterを含めPythonのGUIプログラムは次のようにFrameの導出クラスを定義してオブジェクト指向で書くのが一般的です。

import tkinter as tk

 # tk.Frameを継承したFrame1クラスを作成
class Frame1(tk.Frame):
    def __init__(self, master=None): # コンストラクタを定義
        super().__init__(master) # 継承元クラス(tk.Frame)のコンストラクタを呼び出し

        #ウィンドウの設定
        master.title("ウィンドウのタイトル")
        master.geometry("400x300") # 幅と高さを指定

        # フレームの設定
        self.config(bg="whitesmoke") # 背景色を指定
        self.propagate(False) # フレームのpropagate設定 (この設定がTrueだと内側のwidgetに合わせたフレームサイズになる)

        # 実行内容
        self.pack() # フレームを配置
        self.create_widget() # 下記で定義しているcreate_widgetメソッドを実行

    #create_widgetメソッドを定義
    def create_widget(self):

        # ラベルを作成
        self.label1 = tk.Label(self.master, text=u"これはラベルです")
        self.label1.pack()

        # エントリーを作成
        self.entry1 = tk.Entry(self.master)
        self.entry1.insert(tk.END, u"これはエントリーです")
        self.entry1.pack()

        # ボタンを作成
        button1 = tk.Button(self.master, text=u"これはボタンです")
        button1.pack()

if __name__ == "__main__": # このファイルが実行されている場合の処理
    root = tk.Tk() # rootインスタンスを生成
    f1 = Frame1(master=root) # Frame1クラスからf1インスタンスを生成
    f1.mainloop() # f1インスタンスのイベントハンドラを呼び出し

見た目上はラベル、エントリー、ボタンをそのまま配置したのと変わりませんが、このコードではそれらのウィジェットはFrame1という1つのフレームにまとめられているため効率的に管理・運用できます。

フレームを(Frame)入れ子にする

フレームを入れ子にすることで複雑なウィンドウを作ることができます。

次のコードではメインフレームの中にframe1とframe2という2つのフレームを含み、frame1とframe2はそれぞれ4つのラベルウィジェットを含んでいます。

import tkinter as tk

 # tk.Frameを継承したApplicationクラスを作成
class Application(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master,  width=200, height=150)

        # ウィンドウの設定
        self.master.title("ウィンドウのタイトル")

        # 実行内容
        self.pack() # メインフレームを配置
        self.create_widget() # create_widgetメソッドを実行

    #create_widgetメソッドを定義
    def create_widget(self):

        # 1つ目のフレーム
        frame1 = tk.Frame(self.master, relief=tk.RIDGE, bd=2) # tk.Frameクラスからframe1インスタンスを生成
        list1 = [("A", "lightskyblue"), ("B", "khaki"), ("C", "yellowgreen"), ("D", "hotpink")] # list1リストを定義
        for text, color in list1: # ループ開始
            label=tk.Label(frame1, text=text, bg=color, font=("20")) # labelウィジェットを作成
            label.pack(side=tk.LEFT) # labelウィジェットを配置
        frame1.place(relx=0.1, rely=0.1) # frame1フレームを配置

        # 2つ目のフレーム
        frame2 = tk.Frame(self.master, relief=tk.RIDGE, bd=2) # tk.Frameクラスからframe2インスタンスを生成
        list2 = [("A", "lightskyblue"), ("B", "khaki"), ("C", "yellowgreen"), ("D", "hotpink")] # list2リストを定義
        for i, (text, color) in enumerate(list2): # ループ開始
            label=tk.Label(frame2, text=text, bg=color, font=("20")) # labelウィジェットを作成
            label.grid(row=i//2, column=i%2) # labelウィジェットを配置
        frame2.place(relx=0.6, rely=0.5) # frame2フレームを配置

if __name__ == "__main__":
    root = tk.Tk()
    app = Application(master=root)
    app.mainloop()

このようにTkinterの階層構造の構成を理解してFrameウィジェットを使いこなすことで、複雑なウィンドウ構成を実現することができます。

このエントリーをはてなブックマークに追加

コメントを残す

頂いたコメントは一読した後表示させて頂いております。
反映まで数日かかる場合もございますがご了承下さい。