1. はじめに
Tkinter には、ボタンなどを配置するためのレイアウトマネージャとして、grid, pack, place が存在する。
本記事では、どのレイアウトマネージャを常用するのが適切であるかを説明する。
2. レイアウトマネージャ
grid
ウィジェットをグリッド状に配置する。
Excel のセルのようなイメージ。
引数に、何行目・何列目に配置するかを指定する。
各行・列の幅や高さは同じになるとは限らず、配置ウィジェットが必要とするサイズに応じて決まる。また、grid_rowconfigure, grid_columnconfigure の weight を指定することで、指定した比率で行や列に余ったスペースを配分することが可能。
import tkinter as tk
from tkinter import ttk
if __name__ == '__main__':
root = tk.Tk()
# ボタンの配置数
rows = 5
columns = 5
# リサイズ時に配置領域をウィンドウに合わせて伸縮させるため、
# 行・列に余ったスペースを配分する設定
root.rowconfigure(tuple(range(rows)), weight=1)
root.columnconfigure(tuple(range(columns)), weight=1)
# ボタンを配置
for y in range(rows):
for x in range(columns):
ttk.Button(root, text=f'({x}, {y})').grid(row=y, column=x)
root.mainloop()
pack
ウィジェットを指定した方向に沿って配置する。
ウィジェットを順番に並べていくイメージ。
引数の side を使って、上・下・左・右のどの方向から配置するかを指定する。
ウィジェットは基本的に、配置に必要なサイズを確保する。また、fillやexpandを指定することで、余ったスペースを使ってウィジェットや配置領域を伸縮させることが可能。
import tkinter as tk
from tkinter import ttk
if __name__ == '__main__':
root = tk.Tk()
# ボタンを配置
for i in range(5):
ttk.Button(root, text=f'{i}').pack(
side=tk.LEFT,
expand=True
)
root.mainloop()
place
ウィジェットを指定した座標に配置する。
引数にウィジェット左上のx座標・y座標を指定する。
ウィジェットは基本的に、配置に必要なサイズを確保する。width, height によって、サイズを指定することも可能。
import tkinter as tk
from tkinter import ttk
if __name__ == '__main__':
root = tk.Tk()
# ボタンを配置
ttk.Button(root, text='Button').place(x=10, y=50)
root.mainloop()
3. place の問題点
上記の説明を見ると、place で座標を直接指定できるため、初心者には位置関係が分かりやすく見える。
しかし、絶対座標の指定はGUIの外観や保守面で、以下のような大きな問題が発生する。
- ウィンドウリサイズ時のレイアウト全体の配置バランスの崩れ
- ウィジェットサイズ変更時の配置のズレ
- ウィジェット同士の干渉
- テキスト長可変時の表示崩れ
- 実行環境変化による表示崩れ
- 都度座標を調整するための開発工数増加
- レイアウト設計への要求対応が困難(ウィンドウ全体に等間隔にウィジェットを配置するなど)
など。
これらは全て place による絶対座標指定に起因する。
開発をするうえで、実行環境の変化や外観仕様の変更などには対応可能な形式を取ることが最低条件である。
つまり、place による絶対座標の指定は、常用すべきではないといえる。
(place には relx, rely などの相対配置も存在するが、grid や pack で同じことができるなら grid や pack を使うほうが可読性も高い。)
4. まとめ
以上の内容から、レイアウトマネージャを次のように使い分けるのが適切である。
| レイアウトマネージャ | 説明 | 通常用途での推奨度 |
|---|---|---|
grid |
行列構造をもつ配置。tk.Frame と組み合わせた複雑な配置。 |
◎ |
pack |
方向に沿った配置。 単純な配置。 | ○ |
place |
オーバーレイ表示や画像の上にウィジェットを配置するなどの特殊用途。基本的には避ける。 | × |
また、Python の公式ドキュメントでも、一般的には grid を使い、place は特殊用途向きという位置づけとなっている。
grid
It is the most flexible manager and the one to reach for by default:
place
It offers the most control but the least automatic behavior, and is used the least; it suits special cases such as overlapping widgets or precise custom layouts.
Google Translate 和訳
grid
これは最も柔軟性が高く、まず最初に選ぶべきマネージャーです。
place
最も高い制御性を持つ一方で自動的な動作は最小限にとどまり、使用頻度も最も低い方法です。ウィジェットの重なりや精密なカスタムレイアウトといった特殊なケースに適しています。