はじめに
今回は、tkinterモジュールの.grid()について掘り下げて解説します。
Python+tkinterの導入が済んでおり、基本操作が行える事を前提で進めます。
↓前提知識はこちらをご覧ください↓

.grid()は、正直使いにくいです。
ちゃんと作り込みたいなら「.place()」の方がおすすめです。
.grid()の配置
.grid()はウィジットを作成後、そのウィジット名.grid()だけで配置できます。

初期状態では、左上に配置されます。


複数配置した場合、左上で重なります。
領域を拡大する(ipadx / y)
ipadx / yを使うと、ウィジットの領域を拡大できます。
・ipadx = 横方向の余白を広げる(pxを数値で指定)
・ipady = 縦方向の余白を広げる(pxを数値で指定)
この2つを.grid()内に描画。

すると、Labelなどの要素の領域を拡大できます。


Buttonウィジットなどに使うと、ボタンの有効範囲が広がります。
以上が、領域を拡大する(ipadx / y)の解説です。
要素を並べる(column / row)
.grid()は、要素は「column」と「row」を使って並べます。
・column = 横方向の並び順を指定(0~)
・row = 縦方向の並び順を指定(0~)
初期状態では、この2つは両方「0」に設定されてます。
この設定を両方「0」にしたウィジットを複製して3つ配置。


違いが分かりやすいように色だけ変えてます。
・fg = 文字色(16進数表記)
・bg =背景色(16進数表記)
※16進数表記の詳細は “こちら” をご覧ください。
すると、1つだけ表示されてるように見えます。
これは3つの要素が重なってるのが原因です。

そこでLabel_2のcolumnを「1」に設定。
Label_3のrowを「1」に設定。

すると… 位置がズレて3つの要素が見えるようになります。
・column = 1 → 横方向に1つズラして並べる
・row = 1 → 縦方向に1つズラして並べる

そしたら、今度はLabel_2のcolumn/rowを=1に設定。
Label_3のcolumn/rowを=2に設定。

すると… 右下にズレて斜めに要素が配置されていきます。

要素の並び方はウィジットの大きさで決まる
要素の並び方は “ウィジットの大きさ” を元に決まります。
試しに「Label_2」のipadx/yを調整して、大きさを変更。

すると、Label_2のウィジットが大きくなります。
そして、Label_2の大きさに合わせて、Label_3の配置がズレたことが分かります。

以上が、要素の並び方はウィジットの大きさで決まるの解説です。
column/rowの数字を飛ばした場合の挙動
column/rowの数字を飛ばした場合、飛ばした数字は0pxと扱われます。
そして、見た目的には変化が無い状態になります。
試しにLabel_2のcolumn/rowの値を「4」、Label3を「5」に設定。

すると… 2と3が0pxで生成された後、4と5が処理されて配置されます。
なので、見た目的には変化が無い形になります。


検証はしてないですが…
無駄な負荷が増えてると思うので、
数値は飛ばして設定しない事をおすすめします。
以上が、column/rowの数字を飛ばした場合の挙動です。
ウィジットが2つある場合は大きい方で決まる
大きさが違うウィジットを「column = 0」の位置に並べます。
そして、Label_3の「column = 1」にして、どの位置に配置されるか確認。

すると… Label_3は大きい方の横幅に合わせて位置が決まります。
→ つまり、大きい方を基準に位置が決まりました。

縦方向も同じ挙動です。
以上が、ウィジットが2つある場合は大きい方で決まるの解説です。
余白を作る(padx / y)
余白は「padx」と「pady」で設定できます。
重要なのは「ipadx」と「ipady」とは別物という事です。

・ipadx/yは “領域を拡大” します
・padx/yは領域の外に “空白” を作ります
↓先ほどの処理に「padx/y=20」と設定した処理を追加。

すると、ipadx/yで設定した外側に空白の領域が発生します。

この空白が「padx/y」の効果です。
設定したピクセル数の空白を “領域の外” に作り出します。


20pxの余白を設定した場合…
上下に10pxの余白が生成されます。
(設定値÷2の値)
以上が、余白を作る(padx / y)処理の解説です。
グリット上での配置を指定(sticky =)
sticky = を使うと、余白上でどの位置に配置するかを設定できます。
試しに、先ほどの処理にLabel_4を追加し「sticky = tkkinter.SE」を設定。
「column/row」を設定して配置するグリットを指定。

すると、Label_4がグリットの右下に配置されます。
「SE」は方角を元に、位置を表します。

方向を変える処理は下記。
【stickyで方向を変える】
・sticky = tkinter.N → 上側に配置
・sticky = tkinter.NE → 右上に配置
・sticky = tkinter.E → 右側に配置
・sticky = tkinter.SE → 右下に配置
・sticky = tkinter.S → 下側に配置
・sticky = tkinter.SW → 左下に配置
・sticky = tkinter.W → 左側に配置
・sticky = tkinter.NW → 左上に配置
・sticky = tkinter.CENTER → 中央に配置
こちらの図のような配置になります。


2方向の指定の際に、注意点が必要です。
「NW」だと動きますが「WN」だと動かない問題があります。
この “組み合わせ” の並び順に気を付けてください。
また、こちらのような省略表記も可能です。
【stickyの省略表記】
・sticky = "n" → 上側に配置
・sticky = "ne" → 右上に配置
・sticky = "e" → 右側に配置
・sticky = "se" → 右下に配置
・sticky = "s" → 下側に配置
・sticky = "sw" → 左下に配置
・sticky = "w" → 左側に配置
・sticky = "ne" → 左上に配置
・sticky = "center" → 中央に配置
※「.tkinter」を消して「""」で囲った小文字で方向を入力する形になります。
また、stickyは = NSEWのような4方向の入力も可能です。

4方向を入力した場合、グリッドの限界値まで領域が拡大します。

また「上と下」や「右と左」といった相反する2方向も設定可能。

こちらを設定した場合は、2方向に対して伸びる処理になります。

ここまでをまとめると下記。
【stickyで領域を拡大する】
・sticky = tkinter.NSEW → 上下左右に拡大
・sticky = tkinter.NS → 右上に配置
・sticky = tkinter.EW → 右側に配置
また、こちらも下記のような省略表記が可能です。
【sticky領域拡大の省略表記】
・sticky = "nsew" → 上下左右に拡大
・sticky = "ns" → 右上に配置
・sticky = "ew" → 右側に配置
また、これらの条件を「+」で合成する事もできます。
「sticky = “ew” + sticky = “s”」の条件を合成。

すると、sticky = “ew”で左右に拡大。
+sticky = “s”で下方向に配置された状態が作れたりします。

以上が、グリット上で配置を指定する「sticky =」の解説です。
複数のグリッドをまたぐ(columnspan/rowspan)
下記の設定で、複数のグリッドをまたいだウィジットを作れます。
【グリッドのまたぎ方】
◆横方向
・column = で開始位置を設定
・columnspan = で終了位置+1の値を設定
◆縦方向
・row = で開始位置を設定
・rowspan = で終了位置+1の値を設定

ちょっと謎な挙動ですが…
span = 系は「1」スタートになるようです。
なので +1 した値を設定します。
column0~2の要素を使った状態にします。
そして、column = 0 / columnspan = 3のウィジットを作成。
row = 3にして位置を分かりやすくします。

すると、横幅0~3のウィジットを作成できます。


※終了位置の設定は+1する必要があるので注意
縦方向も同様に、row0~2を使った状態に設定。
そして、row = 0 / rowspan = 3のウィジットを作成。
column = 3にして位置を分かりやすくします。

すると、縦幅0~3のウィジットを作成できます。

以上が、複数のグリッドをまたぐ(columnspan/rowspan)の使い方です。
画面サイズに合わせてウィジットの大きさを変える(column/rowconfigure)
先ほど作った画面は… 画面サイズを変えると図が見切れます。

こちらのgifのように、画面サイズ変更とウィジットの大きさが同期してません。

これを同期させるのが「columnconfigure / rowconfigure」です。
まず、違いを分かりやすくするように「sticky = “nsew”」を設定。
さらに、余白を作る処理「padx / y」を消します。

すべての要素で同様の設定を行います。
※ipadx / yはウィジットの大きさの差を作るため残してます。

そして、下の方に下記のような表記を追加。
【画面サイズに合わせて大きさを変える処理】
・root.grid_columnconfigure("対象グリッド" , weight = "影響度")
・root.grid_rowconfigure("対象グリッド" , weight = "影響度")

※影響度は「column/rowconfigure」を複数配置した際に違いが出ます。
この2つを書く事で、縦と横の対象先を指定できます。
そして、weightは「column/rowconfigure」が1つだけなら = 1で大丈夫です。

すると、指定した要素が画面の大きさに合わせて自動拡大されます。
今回の場合、対象は「0」なので、column/row = 0のグリッドに影響が出ます。


これで、俗にいう「レスポンシブデザイン」が作れます。
動かすと、こぎらのgifのような動きになります。
0,0以外の要素は大きさ固定なので、小さくすると0,0の要素が消えます。

そしたら、column/rowconfigureの対象を「1」に設定。

すると、column/row = 1のグリッドに影響が出るようになります。

column/rowconfigureの値は別のモノでも設定可能です。

columnconfigureの対象が「2」なら、column = 2の所で大きさを調整。
rowconfigureの対象を「3」row = 3の所で大きさを調整する形になります。

そして、下gifのような動きになります。


このあたり、実際に使って見ると頭が混乱してきて難しいと思います。
さらに、グリットサイズがウィジットの最大幅で決まるので…
結局、.grid()は使いにくい。
だったら、最初から.place()使った方が良いよねという答えに行きつきます。
.placeはもっと簡単に画面サイズに合わせてウィジットの大きさを変えれます。
さらに、サイズも個別に設定可能。(ウィジットの最大幅で自動決定しない)
↓.place()については、こちらで解説。
すべてを均等に拡大する場合は「column/rowconfigure = 0~全グリットの数」を設定。
そして、全てのweightを「1」に設定します。

すると、全ての要素が画面サイズに合わせて拡大縮小します。

こちらのような感じで動きます。


赤色が微妙に大きいのは、おそらく「ipadx/y」の影響です。
そして「weight =」の値を変えると、画面サイズの影響度が変わります。
影響度は他の要素の値を見て “相対的に” 決まります。
他の要素が「weight = 1」の場合、1つだけ「ewight = 10」にすると…
理論的には10倍拡大されますが…

テキストの文字幅、ipadx/yなどの関係で実際には「10倍」にはならないです。
なので、ちょっと大きくできるぐらいしか設定できません。


このあたりになってくると、書いてみて動かして確認。
上手くいかなかったら、描き直して再調整。
みたいな “試行錯誤” の世界になってきます。
※そして、細かく作り込むなら「.place()」の方が良いよねと言う答えに行きつきます。
違いが分かりやすくなるように、ipadx/yなどを削除。

すると、ちょっと10倍に近い形で拡大されます。

次は、x,y=「2,2」のweight =の値を「3」に設定。

すると、x,y = 2の要素(灰色)が、理論値3倍大きくなります。

以上が、画面サイズに合わせてウィジットの大きさを変える(column/rowconfigure)の使い方です。

次は、このcolummn/rowconfigureの中で使えるパラメータを解説します。
ウィジットの最小値設定(minsize)
column/rowconfigure()内にminsizeと打ち込む事で最小値を設定できます。
・cloumncongigure()に入れた値 → 横幅の最小値
・rowcongigure()に入れた値 → 縦幅の最小値

最小値を設定すると、縮小した際にその値より小さくならないように動きます。

↓gifだとこのような動きになります。

以上が、最小値(minsize)の設定です。
ウィジットの大きさ設定(pad)
column/rowconfigure()内にpadと打ち込む事でウィジットの大きさを設定できます。
役割的には「ipadx/y」や「minsize」に近いモノになります。
・cloumncongigure()に入れた値 → 横幅の大きさ
・rowcongigure()に入れた値 → 縦幅の大きさ

こちらを設定すると、グリッドの大きさが変わります。

↓gifのような感じの動きになります。


役割や動き方的に、ほぼ「minsize」と同じと考えていいと思います。
以上が、ウィジットの大きさ設定(pad)の設定です。
まとめ
今回は、Pythonのtkinterモジュールで.grid()を使ったウィジットの配置方法を紹介しました
・使いにくいので「.place()」を使うのがおすすめ
・基本的な考え方は「column」で横位置、「row」で縦位置を設定する
・複数ウィジットを配置した場合の大きさはウィジットの最大幅で決まる
・column/rowspanで複数のグリットをまたぐことができる
・column/rowconfigureで画面の大きさに合わせてサイズ変更も可能
また、他にもPythonやプログラムについて解説してます。
ぜひ、こちらもご覧ください。
コメント