あけましておめでとうございます。2022年もよろしくおねがいします。
昨晩は妻からプレゼントしてもらったニューマットレスを敷いて寝たのですが、マットレスが変わるとこうも寝心地が変わるものかと驚いています。 まるでホテルの良質なベッドで寝たかのような寝心地でした。
元旦から良い睡眠させてもらいました。
肩のこりも幾分楽になっているような気がする。
tkinterのgirdを用いたウィジェットの配置について
さて、本題。
tkinterではウィジェットの配置にはpack, grid, placeを用いるが、今回はこのgridについて調べたのでそちらについて書いていく。
tkinterのgridはrow(行番号)とcolumn(列番号)を指定しながらウィジェットを配置する。
イメージ的にはExcelのセルに配置するようなイメージとなる。
例えば下記のようなコードを実行した場合、
import tkinter as tk class App: def __init__(self, root): self.root = root root.title("grid サンプル") root.geometry("600x400") tk.Label(root, text="ラベル1").grid(row=0, column=0) tk.Label(root, text="ラベル2").grid(row=0, column=1) tk.Label(root, text="ラベル3").grid(row=1, column=0) tk.Label(root, text="ラベル4").grid(row=2, column=1) def main(): root = tk.Tk() app = App(root) app.root.mainloop() if __name__ == "__main__": main()
下記のようなウィジェットの配置となる。
[余談] gridの公式ドキュメントについて
なお、ここでtkinterのgridに関する公式ドキュメントを探してみた。
というのも tkinter grid python
などで検索すると公式ドキュメントは検索結果の1ページめには出てこない。
なぜ公式ドキュメントが一枚目に出てこないのか?と思いつつ、公式ページからたどってたどり着いたgridの公式ドキュメントがこちらとなる。
grid manual page - Tk Built-In Commands
なかなか無骨なデザインになっているので、これを読んでいくよりはどこかのブログで分かりやすく解説されている記事でも読んだほうが精神的には楽かもしれない...
ただ、公式ドキュメントであるし、網羅的にはまとまっているので困ったらこちらを見るのはありかもしれない。
gridでExcelのセル結合的なことを実現させる
さきほどgridはExcelのセル的な考えに近いと書いたが、例えばセル結合的なことを行ったウィジェット配置も可能で、その場合には columnspan
という属性を渡す。
import tkinter as tk class App: def __init__(self, root): self.root = root root.title("grid サンプル") root.geometry("600x400") tk.Label(root, text="ラベル1").grid(row=0, column=0) tk.Label(root, text="ラベル2").grid(row=0, column=1) tk.Label(root, text="ラベル3").grid(row=1, column=0, columnspan=2) # columnspanを追加 tk.Label(root, text="ラベル4").grid(row=2, column=1) def main(): root = tk.Tk() app = App(root) app.root.mainloop() if __name__ == "__main__": main()
columnspan
はデフォルトでは1が渡されているがこれを2にすることで2つ分のセルを結合したような状態となる。
実行結果は下記の通り。
ラベル3の位置が変わっていることが分かる。
同じように rowspan
という属性もあり、これは縦方向のセルを結合するために利用される。
gridのオプションについて
- column - ウィジェットを配置する列番号(0はじまり)
- row - ウィジェットを配置する行番号(0はじまり)
- columnspan - 横方向に結合する数(デフォルトは1)
- rowspan - 縦方向に結合する数(デフォルトは1)
またgridのオプションには隙間(空白)を設定できるものもある。
(webで言うmarginとpadding)
- ipadx - ウィジェット内側の横方向の隙間(デフォルトは0)
- ipady - ウィジェット内側の縦方向の隙間(デフォルトは0)
- padx - ウィジェット外側の横方向の隙間(デフォルトは0)
- pady - ウィジェット外側の縦方向の隙間(デフォルトは0)
ipadx, ipadyがpadding的なものとなり、padx, padyがmargin的な使い方となる。
実際にipadyでlabelの内側の隙間(padding)を広げたサンプル
import tkinter as tk class App: def __init__(self, root): self.root = root root.title("grid サンプル") root.geometry("600x400") tk.Label(root, text="ラベル1", bg="green").grid(row=0, column=0, ipady=50) # 分かりやすく50に設定 tk.Label(root, text="ラベル2", bg="coral").grid(row=0, column=1) tk.Label(root, text="ラベル3", bg="blue").grid(row=1, column=0) tk.Label(root, text="ラベル4", bg="red").grid(row=2, column=1) def main(): root = tk.Tk() app = App(root) app.root.mainloop() if __name__ == "__main__": main()
すると下記のようになる。
gridのstickyオプションについて
stickyオプションを利用すると、指定した方向に対してグリッド内いっぱいにウィジェットが広がる。
具体的にどのような挙動をするか、まずはサンプルを用意する。
import tkinter as tk class App: def __init__(self, root): self.root = root root.title("grid サンプル") root.geometry("600x400") tk.Label(root, text="ラベル1", bg="green").grid(row=0, column=0) tk.Label(root, text="ラベル2", bg="coral", width=50).grid(row=0, column=1) tk.Label(root, text="ラベル3", bg="blue").grid(row=1, column=0) tk.Label(root, text="ラベル4", bg="red").grid(row=2, column=1) def main(): root = tk.Tk() app = App(root) app.root.mainloop() if __name__ == "__main__": main()
このコードを実行すると、下記のようなウィジェット配置となる。
次にこのサンプルの ラベル4
にstickyオプションを指定する。
指定内容は左右いっぱいに広げるという内容となる。
import tkinter as tk class App: def __init__(self, root): self.root = root root.title("grid サンプル") root.geometry("600x400") tk.Label(root, text="ラベル1", bg="green").grid(row=0, column=0) tk.Label(root, text="ラベル2", bg="coral", width=50).grid(row=0, column=1) tk.Label(root, text="ラベル3", bg="blue").grid(row=1, column=0) tk.Label(root, text="ラベル4", bg="red").grid(row=2, column=1, sticky=tk.EW) # stickyを指定 def main(): root = tk.Tk() app = App(root) app.root.mainloop() if __name__ == "__main__": main()
すると、下記の通りの配置となる。
本来widthを指定していないラベル4がセルの左右いっぱいに広げられているのはstickyによるものだ。
例えば右に寄せて配置したければ sticky=tk.E
と指定すれば良い。
このstickyで方向を指定する際のEとかWとかは東西南北から取られていると思われる。
- E - 東、つまり右方向
- W - 西、つまり左方向
- N - 北、つまり上方向
- S - 南、つまり下方向
上のサンプルに書いたように tk.EW
と組み合わせでも記載できる。