【Tkinter】gridメソッドを解説!

Tkinter gridメソッド

こんにちは、Youtaです。

Tkinterではウィジェットの配置方法が\(3\)つあります。

今回焦点を当てるのはgridメソッドです。

Tkinterでウィジェットを配置する3つの方法

本記事は、gridメソッドの仕様をすべて解説します。

誰でも必ず理解できるように、豊富な説明と図解を盛り込みました。

早速、gridメソッドを見ていきましょう!

gridメソッド

gridメソッドは格子状にウィジェットを配置します。

位置を行番号・列番号で指定でき、複雑なレイアウトを簡単に作成するのに役立ちます。

gridメソッドの構文です。

ウィジェット.grid(オプション=値, ...)

次章では、上記のオプションに指定できるものをご紹介します。

オプション

gridメソッドには\(10\)個のオプション引数があります。

変数名データ型説明
row整数ウィジェットを配置するセルの行番号
column整数ウィジェットを配置するセルの列番号
rowspan整数ウィジェットがまたがるセルの行数
columnspan整数ウィジェットがまたがるセルの列数
ipadx整数ウィジェット内側の\(x\)方向の余白
ipady整数ウィジェット内側の\(y\)方向の余白
padx整数
タプル
ウィジェット外側の\(x\)方向の余白
pady整数
タプル
ウィジェット外側の\(y\)方向の余白
sticky文字列ウィジェットのセル内での配置場所
in_ウィジェット親ウィジェット(コンテナ)を指定
gridメソッドの引数

rowcolumn

row・columnの図解

rowcolumnは、ウィジェットを配置するセルの行番号列番号です。

行・列共に、番号は\(0\)から始まります。

rowcolumnを指定して、任意のセルにウィジェットを置く例です。

import tkinter as tk

root = tk.Tk()

# ラベル1をグリッドの位置(0, 0)に配置
label1 = tk.Label(root, text="Label1", bg="lightblue")
label1.grid(row=0, column=0)

# ラベル2をグリッドの位置(0, 1)に配置
label2 = tk.Label(root, text="Label2", bg="lightgreen")
label2.grid(row=0, column=1)

# ラベル3をグリッドの位置(1, 0)に配置
label3 = tk.Label(root, text="Label3", bg="lightpink")
label3.grid(row=1, column=0)

# ラベル4をグリッドの位置(1, 1)に配置
label4 = tk.Label(root, text="Label4", bg="lightyellow")
label4.grid(row=1, column=1)

root.mainloop()

実行例です。

row・columnの適用例

rowspancolumnspan

rowspan・columnspanの図解

rowspancolumnspanは、ウィジェットを複数の行や列を占めるように配置します。

数値の分だけセルを結合します。

rowspancolumnspanを使ってセルを結合する例です。

import tkinter as tk

root = tk.Tk()

# ラベル1をグリッドの位置(0, 0)に配置し、2列にまたがるように指定
label1 = tk.Label(root, text="Label1", bg="lightblue")
label1.grid(row=0, column=0, columnspan=2)

# ラベル2をグリッドの位置(1, 0)に配置し、2行にまたがるように指定
label2 = tk.Label(root, text="Label2", bg="lightgreen")
label2.grid(row=1, column=0, rowspan=2)

# ラベル3をグリッドの位置(1, 1)に配置
label3 = tk.Label(root, text="Label3", bg="lightpink")
label3.grid(row=1, column=1)

# ラベル4をグリッドの位置(2, 1)に配置
label4 = tk.Label(root, text="Label4", bg="lightyellow")
label4.grid(row=2, column=1)

root.mainloop()

実行例です。

rowspan・columnspanの適用例

padxpady

padx・padyの図解

padxpadyは、ウィジェットの外側の余白(単位: px)を指定します。

CSSのmarginのようなもので、周囲のウィジェットとの間に隙間を入れます。

基本は整数での指定ですが、タプルもOKです。

より詳細な位置に余白が入ります。

child.grid(
    padx=(a, b),  # 水平方向の余白: aは左側の余白、bは右側の余白
    pady=(c, d),  # 垂直方向の余白: cは上側の余白、dは下側の余白
)
先生
先生

後述のipadxipadyはタプルを渡せません。

padxpadyでウィジェット間に余白を入れる場合と入れない場合の違いを見ます。

import tkinter as tk

root = tk.Tk()

# ラベル1: 余白なし
label1 = tk.Label(root, text="Label1", bg="lightblue")
label1.grid(row=0, column=0)

# ラベル2: padxあり
label2 = tk.Label(root, text="Label2", bg="lightgreen")
label2.grid(row=0, column=1, padx=20)

# ラベル3: 余白なし
label3 = tk.Label(root, text="Label3", bg="lightpink")
label3.grid(row=1, column=0)

# ラベル4: padyあり
label4 = tk.Label(root, text="Label4", bg="lightyellow")
label4.grid(row=1, column=1, pady=15)

root.mainloop()

実行例です。

padx・padyの適用例

ipadxipady

ipadx・ipadyの図解

ipadxipadyは、ウィジェットの内側の余白(単位: px)を指定します。

CSSのpaddingのようなもので、ウィジェットが占める領域を大きくします。

ipadxipadyで内部に余白を入れる場合と入れない場合の違いを見てみましょう。

import tkinter as tk

root = tk.Tk()

# ラベル1: 余白なし
label1 = tk.Label(root, text="Label1", bg="lightblue")
label1.grid(row=0, column=0)

# ラベル2: ipadxあり
label2 = tk.Label(root, text="Label2", bg="lightgreen")
label2.grid(row=0, column=1, ipadx=20)

# ラベル3: 余白なし
label3 = tk.Label(root, text="Label3", bg="lightpink")
label3.grid(row=1, column=0)

# ラベル4: ipadyあり
label4 = tk.Label(root, text="Label4", bg="lightyellow")
label4.grid(row=1, column=1, ipady=15)

root.mainloop()

実行例です。

ipadx・ipadyの適用例

sticky

stickyの図解

stickyは、ウィジェットをセル内のどの方向に寄せるかを指定します。

stickyの引数は方位を表す文字です。

英語の各方角の頭文字ですので覚えやすいと思います。

文字列寄せる方向
tkiner.N または "n"
tkiner.E または "e"
tkiner.S または "s"
tkiner.W または "w"
tkiner.NE または "ne"右上
tkiner.SE または "se"右下
tkiner.SW または "sw"左下
tkiner.NW または "nw"左上
stickyの引数

またstickyは方角を+演算子で足せます。

例えばsticky=tk.N+tk.Sで、ウィジェット縦に引き伸ばせます

tk.N+tk.Sの代わりにtk.NS"ns"でも構いません。

sticky=tk.NSの図解

(tkintertkと省略しています。)

同様にsticky=tk.E+tk.Wで、ウィジェット横に引き伸ばせます。

tk.E+tk.Wの代わりにtk.EW"ew"でも構いません。

sticky=tk.EWの図解

さらにsticky=tk.N+tk.E+tk.S+tk.Wで、ウィジェットを上下左右に引き伸ばせます。

tk.N+tk.E+tk.S+tk.Wの代わりにtk.NSEW"nsew"でも構いません。

sticky=tk.NSEWの図解

他の合わせ技、例えばsticky=tk.N+tk.S+tk.Wもいけます("nsw"でも可)。

sticky=tk.NS+tk.Wの図解

stickyを使って、ウィジェットを色々な方角に寄せる例です。

import tkinter as tk

root = tk.Tk()

label1 = tk.Label(root, text="Label1", bg="lightblue")
label1.grid(row=0, column=0, sticky="w")       # 左側に配置

canvas = tk.Canvas(root, bg="lightgreen", width=100, height=50)
canvas.grid(row=0, column=1, sticky="e")      # 右側に配置

entry = tk.Entry(root)
entry.grid(row=0, column=2, sticky="n")       # 上部に配置

button = tk.Button(root, text="Button")
button.grid(row=1, column=0, sticky="s")      # 下部に配置

label2 = tk.Label(root, height=3, width=20, text="Label2", bg="lightpink")
label2.grid(row=1, column=1, sticky="nsew")     # セル全体に広げる

checkbutton = tk.Checkbutton(root, text="Checkbutton", bg="lightyellow")
checkbutton.grid(row=1, column=2, sticky="ne")  # 右上に配置

root.mainloop()

各ウィジェットがバラバラな方向に寄せられていますね。

stickyの適用例

in_

in_の図解

in_は、ウィジェットを配置する親コンテナ(ウィジェット)を指定します。

通常、ウィジェットはコンストラクタの第一引数に指定した親に配置されます。

import tkinter as tk

root = tk.Tk()
frame = tk.Frame()

# 親はroot
label = tk.Label(root)

# root(親)にlabelを配置
label.grid(column=0, row=0)

しかし、in_を使うと後から配置先となる親を変更できるのです。

import tkinter as tk

root = tk.Tk()
frame = tk.Frame()

# 親はroot
label = tk.Label(root)

# frame(新しい親)にlabelを配置
label.grid(column=0, row=0, in_=frame)

配置先を後から変えられるので、レイアウトに自由度が増しますね。

in_を利用して、ウィジェットの配置位置を切り替える例です。

import tkinter as tk

# ウィジェットの状態を切り替える関数
def toggle():
    global is_in_frame

    # 現在の状態に応じてadd_label_to_frame()またはremove_label_from_frame()を呼び出す
    if is_in_frame:
        remove_label_from_frame()
    else:
        add_label_to_frame()

    is_in_frame = not is_in_frame

# labelをlabel_frame内に配置する関数
def add_label_to_frame():
    label.grid(in_=label_frame)

# labelをroot内に配置する関数
def remove_label_from_frame():
    label.grid(in_=root)

is_in_frame = False

root = tk.Tk()

# ラベルフレームを作成し、配置する
label_frame = tk.LabelFrame(root, text="LabelFrame", width=100, height=100)
label_frame.grid(row=0, column=0, padx=10, pady=10)

# 切り替えボタンをラベルフレームに配置し、toggle関数を紐づける
button = tk.Button(label_frame, text="Button", command=toggle)
button.grid(row=0, column=0, padx=5, pady=5, sticky="nsew")

# メインのラベルを作成し、rootに配置する
label = tk.Label(root, text="Label", bg="lightblue")
label.grid(row=1, column=0, sticky="nsew", padx=5, pady=5)

root.mainloop()

最初、labellabel_frameの外に配置されます。

in_を適用する前

ボタンを押すと、labelは新しい親label_frameの中に移動します。

in_を適用して、LabelFrame内にlabelを移動させる

オプションの設定を確認

grid_infoの図解

grid_infoメソッドはgridメソッドのオプションの設定を取得します。

grid_infoメソッドの構文です。

子ウィジェット.grid_info()

具体例を示しましょう。

grid_infoメソッドを使うにあたり、下記の状態を前提とします。

import tkinter as tk

root = tk.Tk()

label = tk.Label(root)
label.grid(row=0, column=0)

gridメソッドの設定を出力してみます。

print(label.grid_info())
# {'in': <tkinter.Tk object .>, 'column': 0, 'row': 0, 'columnspan': 1, 'rowspan': 1, 'ipadx': 0, 'ipady': 0, 'padx': 0, 'pady': 0, 'sticky': ''}

辞書形式で全オプションの設定が取れました。

グリッドの寄せ方を制御

grid_anchorの図解

grid_anchorメソッドは親ウィジェット内での格子の位置を制御します。

grid_anchorメソッドの構文です。

親ウィジェット.grid_anchor(anchor=None)

引数anchorには格子を寄せる方向を指定します。

grid_anchorの引数anchorに指定可能な文字列
文字列寄せる方向
tkiner.N または "n"
tkiner.E または "e"
tkiner.S または "s"
tkiner.W または "w"
tkiner.NE または "ne"右上
tkiner.SE または "se"右下
tkiner.SW または "sw"左下
tkiner.NW または "nw"左上
tkiner.CENTER または "c" 中央
grid_anchorメソッドの引数anchorの種類
すずか
すずか

stickyと何が違うの?

stickyは、セル内でのウィジェットを寄せる方向を決めるのでした。

grid_anchorメソッドは、コンテナ内での格子を寄せる方向を決めます。

stickyとgrid_anchorの違い

grid_anchorメソッドを使って、画面内でセル全体を動かす例です。

import tkinter as tk

root = tk.Tk()
root.geometry("250x250")  # ウィンドウサイズの設定

# 3行4列のグリッドを作成し、各セルにラベルを配置
for row in range(3):
    for col in range(4):
        label = tk.Label(root, text=f"({row}, {col})")
        label.grid(row=row, column=col)

# 変数varの初期値を"nw"に設定
var = tk.StringVar(value="nw")

# varが変更されると、rootのアンカー位置を更新するコールバックを設定
var.trace_add("write", lambda *args: root.grid_anchor(var.get()))

# 配置する方向のオプションを定義
directions = ("n", "s", "e", "w", "ne", "se", "sw", "nw", "c")

# オプションメニューを作成し、配置の方向を選択
option_menu = tk.OptionMenu(root, var, *directions)
option_menu.grid(column=0, row=row+1, columnspan=col+1)

root.mainloop()

一応コメントを書いていますがStringVarの設定部分が難しいと思います。

# 変数varの初期値を"nw"に設定
var = tk.StringVar(value="nw")

# varが変更されると、rootのアンカー位置を更新するコールバックを設定
var.trace_add("write", lambda *args: root.grid_anchor(var.get()))

どうしてもわからない方向けに、下記記事にて丁寧に解説しています。

>> StringVarのtrace_addメソッドで、コールバックを自動で呼び出す方法

さて、コードを実行した画面です。

オプションメニューで方向を選びます。

grid_anchorを試す前の画面。

試しに"s"を選ぶと、グリッド全体が下にシフトするのを確認できます。

grid_anchorにより、格子全体が画面の下に寄せられる

ウィジェットを非表示

gridメソッドで配置したウィジェットを非表示にする方法は\(2\)つあります。

それが、grid_forgetgrid_removeメソッドです。

構文は下記の通りです。

子ウィジェット.grid_forget()
子ウィジェット.grid_remove()
すずか
すずか

非表示にしたら戻せないの?

先生
先生

再度gridメソッドを使うと再表示されます。

grid_forgetgrid_removeの違い

すずか
すずか

じゃあ違いは?

先生
先生

gridメソッドのオプション設定を引き継ぐか否かです。

grid_forgetメソッドは、gridメソッドのオプション設定を無効化してしまいます。

したがって、再表示の際には再度オプションを設定する必要があります。

# 配置
子ウィジェット.grid(row=0, column=0, padx=10, pady=10, sticky="w")

# 非表示
子ウィジェット.grid_forget()

# 再表示
子ウィジェット.grid(row=0, column=0, padx=10, pady=10, sticky="w")

一方grid_removeメソッドは、前回指定したオプションの設定を忘れません。

したがって、再表示の際には引数なしでも前回の設定が適用されます。

# 配置
子ウィジェット.grid(row=0, column=0, padx=10, pady=10, sticky="w")

# 非表示
子ウィジェット.grid_remove()

# 再表示
子ウィジェット.grid()

grid_forgetgrid_removeの具体例

grid_forgetメソッドで、ウィジェットの表示・非表示を切り替える例です。

import tkinter as tk

# ウィジェットの状態を切り替える関数
def toggle():
    global is_visible

    # 現在の状態に応じてshow()またはhide()を呼び出す
    if is_visible:
        hide_label()
    else:
        show_label()

    is_visible = not is_visible

# labelを表示する関数
def show_label():
    label.grid(row=0, column=0, padx=10, pady=10, sticky="w")

# labelを非表示にする関数
def hide_label():
    label.grid_forget()

is_visible = True

root = tk.Tk()

label = tk.Label(root, text="Label", bg="lightblue")
show_label()

# 切り替えボタンを配置し、toggle関数を紐づける
button = tk.Button(root, text="Button", command=toggle)
button.grid(row=1, column=0)

root.mainloop()

最初はlabelが見えています。

grid_forgetメソッドを適用する前

ボタンを押すとlabelが消えます。

grid_forgetメソッドを適用して、配置されていたlabelを消す

またgrid_removeメソッドは、再表示の際にオプションの設定を引き継ぐのでしたね。

そのため、showhide関数を次のように書き換えても同じ結果が得られます。

def show_label():
    label.grid()

def hide_label():
    label.grid_remove()

グリッドの行数・列数を取得

grid_sizeメソッドは格子の列数と行数を取得します。

grid_sizeメソッドの構文です。

親ウィジェット.grid_size()

戻り値はタプル(列数, 行数)です。

grid_sizeメソッドで、グリッドのサイズを取得する例です。

下記状態を前提とします。

import tkinter as tk

root = tk.Tk()

# 3行4列のグリッドを作成し、各セルにラベルを配置
for row in range(3):
    for col in range(4):
        label = tk.Label(frame, text=f"({row}, {col})")
        label.grid(row=row, column=col)

print(root.grid_size())

実行例です。

print(root.grid_size())
# (4, 3)

まとめ

Tkinterのgridメソッドをご紹介しました。

最後に軽く復習してから締めましょう。

gridメソッドは格子状にウィジェットを配置します。

そのオプション引数は計\(10\)個ありました。

変数名データ型説明
row整数ウィジェットを配置するセルの行番号
column整数ウィジェットを配置するセルの列番号
rowspan整数ウィジェットがまたがるセルの行数
columnspan整数ウィジェットがまたがるセルの列数
ipadx整数ウィジェット内側の\(x\)方向の余白
ipady整数ウィジェット内側の\(y\)方向の余白
padx整数
タプル
ウィジェット外側の\(x\)方向の余白
pady整数
タプル
ウィジェット外側の\(y\)方向の余白
sticky文字列ウィジェットのセル内での配置場所
in_ウィジェット親ウィジェット(コンテナ)を指定
gridメソッドの引数

またgridメソッドに関連して、下記のような機能を提供するメソッドもありました。

メソッド名説明
grid_infoオプションの設定を確認する。
grid_anchorグリッドの寄せ方を制御する。
grid_forgetウィジェットを非表示にする。
オプションは無効化する。
grid_removeウィジェットを非表示にする。
オプションを保存する。
grid_sizeグリッドの行数・列数を取得する。
gridメソッド関連のメソッド

この記事が皆様のお役に立てたら幸いです。

ご覧いただきありがとうございました。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA