どん底から這い上がるまでの記録

どん底から這い上がりたいけど這い上がれない人がいろいろ書くブログ(主にプログラミング)

【tkinter】grid()を使ったWidgetの配置の方法

 

tkinterではwidget(例:Frame、Canvas)を配置するには3つの方法 grid, pack, placeがあります。

今回はgridに焦点を当ててwidgetの配置方法についてまとめていきます。

 

 

前準備

grid()の使い方について見る前に、template.pyapp.pyを用意します。この2つのプログラムを使ってgrid()の使い方について見ていきます。

 

template.py

import tkinter as tk
from PIL import ImageTk


class Template(tk.Tk):
    def __init__(self, **kwargs):
        super(Template, self).__init__()
        self.title(kwargs.get("title", "tkinter"))
        self.geometry("+{}+{}".format(*kwargs.get("pos", (0, 0))))
        self.resizable(*kwargs.get("resize", (1, 1)))
        try:
            self.iconbitmap(kwargs.get("icon", None))
        except:
            if kwargs.get("icon", None) is not None:
                icon_name = kwargs.get("icon")
                icon_img = ImageTk.PhotoImage(file=icon_name)
                self.tk.call("wm", "iconphoto", self._w, icon_img)

    def run(self):
        self.mainloop()

template.pyはアプリケーションの雛形として用意しました。ここでは、アプリケーションのタイトル、起動時のアプリケーションの位置、アプリケーションの拡大拡小の設定、アプリケーションのアイコンについて設定をすることができます。設定はtemplate.pyを継承したクラスでするようにしてあります。

関連記事 - はじめてのtkinter ウィンドウを作って表示させる

 

app.py

import tkinter as tk
from template import Template


class App(Template):
    def __init__(self):
        super(App, self).__init__()
        self.createWidgets()
        self.attachWidgets()

    def createWidgets(self):
        pass

    def attachWidgets(self):
        pass


if __name__ == "__main__":
    app = App()
    app.run()

template.pyのTemplateクラスを継承しています。今回は特にアプリケーションのタイトル、位置、拡大拡小、アイコンの設定については行いません。createWidgetsWidgetの作成、attachWidgets()で作成したWidgetをウィンドウに配置していきます。

gridの使い方

今回、grid()の使い方を見るにあたり3つのFrame、frame_1frame_2frame_3を用意しました。

    def createWidgets(self):
        self.frame_1 = tk.Frame(self, width=100, height=100, bg="coral")
        self.frame_2 = tk.Frame(self, width=100, height=100, bg="tan")
        self.frame_3 = tk.Frame(self, width=100, height=100, bg="violet")

    def attachWidgets(self):
        self.frame_1.grid()
        self.frame_2.grid()
        self.frame_3.grid()

それぞれgrid()を使ってウィンドウに配置し、プログラムを実行すると

$ python app.py

下のウィンドウが起動します。

f:id:pytry3g:20200103153648p:plain

row, rowspan(行についての設定)

rowwidgetを何行目に配置するかを設定します。

rowspanはデフォルトで1になっていて、指定した場合(2以上)、複数の行にまたがってwidgetが配置されます。

f:id:pytry3g:20200103234610p:plain

上のように3つのFrameを3行にわたって配置するには、

    def attachWidgets(self):
        self.frame_1.grid(row=0)
        self.frame_2.grid(row=1)
        self.frame_3.grid(row=2)

f:id:pytry3g:20200104010101p:plain

 

また、rowspanを3にしたときにFrameを3行にわたって配置するには以下のようにします。

    def attachWidgets(self):
        self.frame_1.grid(rowspan=3, row=0)
        self.frame_2.grid(row=3)
        self.frame_3.grid(row=6)

rowspanを3に設定しているので、3行にまたがってwidgetが配置されるようになっています。したがって、frame_2frame_3rowをそれぞれ3と6に設定しています。

f:id:pytry3g:20200104010310p:plain

column, columnspan(列についての設定)

columnwidgetを何列目に配置するかを設定します。

columnspanはデフォルトで1になっていて、指定した場合(2以上)、複数の列にまたがってwidgetが配置されます。

f:id:pytry3g:20200103205955p:plain

上のように3つのFrameを3列にわたって配置するには、

    def attachWidgets(self):
        self.frame_1.grid(column=0, row=0)
        self.frame_2.grid(column=1, row=0)
        self.frame_3.grid(column=2, row=0)

 

また、columnspanを2にしたときにFrameを3列にわたって配置するには以下のようにします。

    def attachWidgets(self):
        self.frame_1.grid(columnspan=2, column=0, row=0)
        self.frame_2.grid(column=2, row=0)
        self.frame_3.grid(column=4, row=0)

columnspanを2に設定しているので、2列にまたがってwidgetが配置されるようになっています。したがって、frame_2frame_3をそれぞれ2と4に設定しています。

f:id:pytry3g:20200104011005p:plain

sticky(widgetの配置位置と拡大方向)

stickywidgetの配置位置と拡大方向の設定をすることができます。

指定できる定数はSNEWNWNESWSEがあり、例えばsticky=tk.Wとすると、widgetを左に寄せて配置し、sticky=tk.W+tk.Sとすると、widgetを左右に引き伸ばして配置します。さらに、sticky=tk.W+tk.E+tk.N+tk.Sとすると、widgetを全方向に引き伸ばして配置します。

つまり、+がなければ配置位置の設定、+があればwidgetを引き伸ばす方向の設定をすることができます。

widgetの内側と外側のpadding

ipadx, ipady(内側のpadding)

ipadxipadyはそれぞれwidgetの内側の高さと横の長さを設定することができます。デフォルトでは0になっています。

padx, pady(外側のpadding)

padxpadyはそれぞれwidgetの外側の高さと横の長さを設定することができます。デフォルトでは0になっています。

 

createWidgets()attachWidgets()を以下のようにして、paddingの使い方について見ていきます。

    def createWidgets(self):
        self.frame_1 = tk.Frame(self, width=100, height=100, bg="coral")
        self.canvas_red = tk.Canvas(self.frame_1, width=30, height=30, bg="red")
        self.canvas_blue = tk.Canvas(self.frame_1, width=30, height=30, bg="blue")

    def attachWidgets(self):
        self.frame_1.grid()
        self.canvas_red.grid(column=0, row=0)
        self.canvas_blue.grid(column=0, row=1)

このコードを実行すると、下のウィンドウが起動します。

f:id:pytry3g:20200103220232p:plain

 

ipadxipadyをそれぞれ10にして、

    def attachWidgets(self):
        self.frame_1.grid()
        self.canvas_red.grid(column=0, row=0, ipadx=10, ipady=10)
        self.canvas_blue.grid(column=0, row=1)

このコードを実行すると、下のウィンドウが起動します。

f:id:pytry3g:20200103220439p:plain

 

padxpadyをそれぞれ10にして、

    def attachWidgets(self):
        self.frame_1.grid()
        self.canvas_red.grid(column=0, row=0, padx=10, pady=10)
        self.canvas_blue.grid(column=0, row=1)

このコードを実行すると、下のウィンドウが起動します。

f:id:pytry3g:20200103220638p:plain

 

padxpadyipadxipadyと違って、もう少し細かく設定をすることができます。

例えば、padxpadyを以下のようにして

    def attachWidgets(self):
        self.frame_1.grid()
        self.canvas_red.grid(column=0, row=0, padx=(30, 5), pady=(0, 10))
        self.canvas_blue.grid(column=0, row=1)

このコードを実行すると、下のウィンドウが起動します。

f:id:pytry3g:20200103221001p:plain

padxpadyはそれぞれpadx=(左、右)pady=(上、下)と細かく設定をすることができます。

サンプルコード

3つのフレームを使ってレイアウト構成のサンプルを見ていきます。

    def createWidgets(self):
        self.frame_1 = tk.Frame(self, width=100, height=100, bg="coral")
        self.frame_2 = tk.Frame(self, width=100, height=100, bg="tan")
        self.frame_3 = tk.Frame(self, width=100, height=100, bg="violet")

frame_1を左側、frame_2frame_3を右側に上から順に配置する。

f:id:pytry3g:20200103194957p:plain

このレイアウトにするにはgrid()の設定を以下のようにする。

    def attachWidgets(self):
        self.frame_1.grid(rowspan=2, column=0, row=0)
        self.frame_2.grid(column=1, row=0)
        self.frame_3.grid(column=1, row=1)

ただ、これだとframe_1の上下に隙間ができてしまうので、

下のようにするには

f:id:pytry3g:20200103195241p:plain

frame_1の上下の隙間を埋めるにはstickyの設定をtk.N+tk.Sとすることで、frame_1を上下に引き伸ばすことができます。

    def attachWidgets(self):
        self.frame_1.grid(
            rowspan=2,
            column=0, row=0, sticky=tk.N+tk.S
        )
        self.frame_2.grid(column=1, row=0)
        self.frame_3.grid(column=1, row=1)

 

frame_1を上側、frame_2frame_3を下側に左から順に配置する。

f:id:pytry3g:20200103213005p:plain

frame_1の左右の隙間を埋めるためにstickyの設定をtk.W+tk.Eとしています。

    def attachWidgets(self):
        self.frame_1.grid(
            columnspan=2,
            column=0, row=0,
            sticky=tk.W+tk.E
        )
        self.frame_2.grid(column=0, row=1)
        self.frame_3.grid(column=1, row=1)

 

frame_1を下側、frame_2frame_3を上側に左から順に配置する。

f:id:pytry3g:20200103213321p:plain

frame_1の左右の隙間を埋めるためにstickyの設定をtk.W+tk.Eとしています。

    def attachWidgets(self):
        self.frame_1.grid(
            columnspan=2,
            column=0, row=1,
            sticky=tk.W+tk.E
        )
        self.frame_2.grid(column=0, row=0)
        self.frame_3.grid(column=1, row=0)

 

frame_1を右側、frame_2frame_3を左側に上から順に配置する。

f:id:pytry3g:20200103213810p:plain

frame_1の上下の隙間を埋めるためにstickyの設定をtk.S+tk.Nとしています。

    def attachWidgets(self):
        self.frame_1.grid(
            rowspan=2,
            column=1, row=0,
            sticky=tk.S+tk.N
        )
        self.frame_2.grid(column=0, row=0)
        self.frame_3.grid(column=0, row=1)

 

frame_1を左上、frame_2を右上、frame_3を左下、frame_4を右下に配置する。

f:id:pytry3g:20200103214308p:plain

    def createWidgets(self):
        self.frame_1 = tk.Frame(self, width=100, height=100, bg="coral")
        self.frame_2 = tk.Frame(self, width=100, height=100, bg="tan")
        self.frame_3 = tk.Frame(self, width=100, height=100, bg="violet")
        self.frame_4 = tk.Frame(self, width=100, height=100, bg="cyan")

    def attachWidgets(self):
        self.frame_1.grid(column=0, row=0)
        self.frame_2.grid(column=1, row=0)
        self.frame_3.grid(column=0, row=1)
        self.frame_4.grid(column=1, row=1)

おわり

gridの使い方について紹介しました。

tkinterについて他にもいろいろ書いているので、ご興味があるかたはぜひ以下の記事を見てみてください。

www.pytry3g.com

 

参考記事 - The Tkinter Grid Geometry Manager