このページでは Tkinter でのウィジェットの配置について解説します。
Tkinter では「ウィジェットを作成」し、そのウィジェットを親ウィジェットの中(例えばメインウィンドウの中)に「配置」することで、GUI アプリ上にそのウィジェットを表示することができます。
なので「ウィジェットの配置」をしないと、そのウィジェットは画面に表示されません。
また「ウィジェットの配置」をうまく行えれば、アプリの見た目も綺麗になりますし、ユーザーが使用しやすい UI を作成することもできます。
Tkinter では「ウィジェットの配置」を行うためのメソッドとして下記の3つが用意されています。
packgridplace
これらは各種類のウィジェットに用意されているメソッドになります。ここからはこの3つのメソッドについて解説していきたいと思います。
Contents
pack
pack は親ウィジェット上にウィジェットを詰め込むメソッドです。
pack 使用例
pack を使用してウィジェットを配置するサンプルスクリプトは下記のようになります。pack を最後にまとめて実行していますが、これは今後の説明をしやすくするためです。
各ウィジェットのインスタンス作成後〜メインループ実行前であればどこで実行しても良いです。
# -*- coding:utf-8 -*-
import tkinter
# メインウィンドウ作成
app = tkinter.Tk()
app.geometry("600x400")
# 青色のキャンバス作成
canvas1 = tkinter.Canvas(
app,
width=100,
height=50,
bg="blue"
)
# 緑色のキャンバス作成
canvas2 = tkinter.Canvas(
app,
width=50,
height=100,
bg="green"
)
# 1つ目のボタン作成
button1 = tkinter.Button(
app,
width=10,
height=1,
text="ボタン1"
)
# 2つ目のボタン作成
button2 = tkinter.Button(
app,
width=5,
height=2,
text="ボタン\n2"
)
# 各ウィジェットの配置
canvas1.pack()
button1.pack()
button2.pack()
canvas2.pack()
# メインループ
app.mainloop()
実行すると下図のようなアプリが起動します。

pack メソッドを実行したウィジェットから順に「上から順に」どんどん親ウィジェット上(メインウィンドウ上)に詰め込まれていく感じで配置されます(インスタンスを生成した順ではないのに注意)。
こんな感じで、ある方向に対してどんどんウィジェットを詰め込んでいくのが pack メソッドになります(どの方向に対して詰め込んでいくかは後述する引数で指定可能)。
引数なしでも実行できる点も pack メソッドの特徴の1つです。
スポンサーリンク
pack の設定(引数)
pack メソッド指定時にキーワード引数を指定することで、様々な設定を行うことができます。
ここでは pack メソッドに指定可能な下記のキーワードと、そのキーワードで設定できる内容を説明していきます。
使用例に関しては、pack 実行部分のみを示しています(他の部分はpack使用例で示したものと同じですので、この点を頭に入れて読んでいただけると助かります)。
# 各ウィジェットの配置
canvas1.pack()
button1.pack()
button2.pack()
canvas2.pack()
side
side の指定により、「どの方向から順に」ウィジェットを詰め込んでいくかを設定することができます。
指定可能パラメータは下記の4つです。
tkinter.TOP:上から順に(デフォルト)tkinter.BOTTOM:下から順にtkinter.LEFT:左から順にtkinter.RIGHT:右から順に
例えば下記のように side=tkinter.RIGHT と指定すれば、pack メソッド実行順に「右から順に」ウィジェットが詰め込んでいかれます。
# 各ウィジェットの配置
canvas1.pack(
side=tkinter.RIGHT
)
button1.pack(
side=tkinter.RIGHT
)
button2.pack(
side=tkinter.RIGHT
)
canvas2.pack(
side=tkinter.RIGHT
)
アプリ起動時の画面は下のようになります。

ウィジェット毎に異なる side 設定を行うことも可能です。
# 各ウィジェットの配置
canvas1.pack(
side=tkinter.RIGHT
)
button1.pack(
side=tkinter.LEFT
)
button2.pack(
side=tkinter.BOTTOM
)
canvas2.pack(
side=tkinter.TOP
)
expand
expand を True に指定することで、親ウィジェットで使用されていないスペースを利用してウィジェットを配置するスペースを拡大することができます。
例えば先ほどの例だと右から順にウィジェットを並べているので左側にスペースが空いています。

このスペースが expand を True に指定したウィジェットのスペースに割り振られる感じです(そのスペースに対してどこに配置するかは後述する anchor により指定可能です)。

expand の設定例は下記のようになります。
# 各ウィジェットの配置
canvas1.pack(
side=tkinter.RIGHT,
)
button1.pack(
side=tkinter.RIGHT,
)
button2.pack(
side=tkinter.RIGHT,
expand=True
)
canvas2.pack(
side=tkinter.RIGHT,
)
アプリ起動時の画面は下のようになります。

expand=True は複数のウィジェットに指定することも可能です。
# 各ウィジェットの配置
canvas1.pack(
side=tkinter.RIGHT,
expand=True
)
button1.pack(
side=tkinter.RIGHT,
)
button2.pack(
side=tkinter.RIGHT,
expand=True
)
canvas2.pack(
side=tkinter.RIGHT,
)
この場合はアプリ起動時の画面は下図のようになります(ボタン1の周りのスペースも広がっているように見えますが、広がっているのは expand=True を設定している青色のキャンバスとボタン2のみです)。

anchor
anchor を指定することで、詰め込んだウィジェットをどの方向に寄せるのかを設定することができます。
下記のようなパラメータを指定することができます。
tkinter.N:上方向tkinter.S:下方向tkinter.W:左方向tkinter.E:上方向tkinter.NW:左上方向tkinter.NE:右上方向tkinter.SW:左下方向tkinter.SE:右下方向tkinter.CENTER:中央
上方向と北方向に見立てた方角で考えると覚えやすいです。例えば ↓ こんな感じ
- 上:北(
North) - 右上:北東(
NorthEast) - 左下:南西(
SouthWest)
anchor の指定例は下記のようになります。
# 各ウィジェットの配置
canvas1.pack(
side=tkinter.RIGHT,
expand=True,
anchor=tkinter.NE
)
button1.pack(
side=tkinter.RIGHT,
anchor=tkinter.S
)
button2.pack(
side=tkinter.RIGHT,
expand=True,
anchor=tkinter.SW
)
canvas2.pack(
side=tkinter.RIGHT,
anchor=tkinter.CENTER
)
アプリを起動時の画面は下のようになります。

イメージとしては次のようにウィジェットが配置されています。
まず side 設定& expand 設定に基づいて各ウィジェットが右から順に詰め込まれていきます。

さらにこれらのウィジェットが anchor に従って指定された方向に寄せられ、アプリ起動時の画面通りに配置されるというイメージです。

fill
fill を指定することで、ウィジェットを引き伸ばし、与えられたスペースに対していっぱいに広げることができます。
fill に指定できるパラメータは下記の4つになります。
tkinter.NONE:引き伸ばししないtkinter.X:横方向に対してのみ引き伸ばすtkinter.Y:縦方向に対してのみ引き伸ばすtkinter.BOTH:縦横両方向に対して引き伸ばす
fill の指定例は下記のようになります。
# 各ウィジェットの配置
canvas1.pack(
side=tkinter.RIGHT,
expand=True,
fill=tkinter.X
)
button1.pack(
side=tkinter.RIGHT,
fill=tkinter.Y
)
button2.pack(
side=tkinter.RIGHT,
expand=True,
fill=tkinter.BOTH
)
canvas2.pack(
side=tkinter.RIGHT,
fill=tkinter.NONE
)
スクリプトを実行して起動したアプリの画面は下のようになります。

下図の fill を指定しない場合の画面と比較すると違いが分かり易いと思います。
例えば、fill=tkinter.X を指定した青いキャンバスは横方向にのみ引き伸ばされ、fill=tkinter.BOTH を指定したボタン2は縦横両方向に対して引き伸ばしてウィジェットが大きくなっていることが確認できます。

padx・pady
padx と pady を指定することで、ウィジェットの外側の空白サイズを設定することができます。

pady の設定例は下記のようになります。
# 各ウィジェットの配置
canvas1.pack(
pady=100
)
button1.pack()
button2.pack()
canvas2.pack()
スクリプトを実行すると下のような画面のアプリが起動します。pady=100 を指定した青いキャンバスの周り(上下)に 100 px の空白が付加されています。

ipadx・ipady
padx と pady がウィジェットの外側を設定するのに対し、ipadx と ipady ではウィジェットの内側の空白サイズを設定することができます。つまり、ウィジェットのサイズが大きくなります。

ipadx と ipady の設定例は下記のようになります。
# 各ウィジェットの配置
canvas1.pack()
button1.pack(
ipadx=100,
ipady=100
)
button2.pack()
canvas2.pack()
スクリプトを実行すると下のような画面のアプリが起動します。ipadx=100 と ipady=100 を指定したボタン1の内側(上下左右)に 100 px の空白が付加されています。

before・after
通常 pack メソッドでは実行した順番で親ウィジェットに対して詰め込まれていきますが、 before・after を指定することで、 この詰め込まれる順番を制御することができます(正確には詰め込まれる順番を制御したようにウィジェットが配置されます)。
before・after には他のウィジェットのインスタンスを指定し、これにより pack メソッドを実行したウィジェットが詰め込まれる順番が下記のように変わります。
before:指定したウィジェットの前にpackメソッドを実行したウィジェットが詰め込まれるafter:指定したウィジェットの後にpackメソッドを実行したウィジェットが詰め込まれる
before と after の設定例は下記のようになります。
# 各ウィジェットの配置
canvas1.pack()
button1.pack()
button2.pack(
after=canvas1
)
canvas2.pack(
before=canvas1
)
スクリプトを実行すると下のような画面のアプリが起動します。

pack メソッドを実行する順番は canvas1(青のキャンバス)→ button1(ボタン1)→ button2(ボタン2)→ canvas2(緑のキャンバス)ですが、canvas2(緑のキャンバス)の pack 実行時に before=canvas1 を指定しているため、canvas2(緑のキャンバスは canvas1(青のキャンバス)よりも上側に配置されています。
同様に button2(ボタン2)の pack 実行時に after=canvas1 を指定しているため、button2(ボタン2)は canvas1(青のキャンバス)のすぐ下に配置されています。
in_
in_ を指定することで、ウィジェットの配置先となる親ウィジェットを設定することができます。
指定しない場合はウィジェットのインスタンス生成時に指定した親ウィジェットに対して配置されます。
pack 関連のメソッド
pack 関連のメソッドも紹介しておきます。
pack_info
pack_info は実行したウィジェットに対する pack の情報を取得するメソッドです。
要は pack メソッド実行時に設定した情報(辞書)を取得することができます。
# button1はボタンのインスタンス
info = button1.pack_info()
pack_forget
pack_forget は実行したウィジェットを画面から消すメソッドです。
画面からは消えますが、そのウィジェットのインスタンスが消えるわけではないので再度 pack メソッド等で画面に表示することができます(ただし前回指定した設定は忘れ去られているので再度設定が必要)。
# button1はボタンのインスタンス
button1.pack_forget()
pack を使用するメリット・デメリット
引数なしでも実行できるのでとにかく簡単に使用できます。私も一番使用するのがこの packです。
とりあえずアプリの動作確認を行いたいだけであれば pack() さえ実行しておけば良いです。
ただし、pack はウィジェットを1次元に配置することを前提としたメソッドなので、ウィジェットの2次元的な配置には pack は向きません。
スポンサーリンク
grid
grid は親ウィジェットを2次元的に複数のセルに分割し、各セルにウィジェットを配置するメソッドです。簡単にウィジェットを2次元的に配列できるところが特徴です。
grid 使用例
grid を使用してウィジェットを配置するサンプルスクリプトは下記のようになります。grid を最後にまとめて実行していますが、これは今後の説明をしやすくするためです。
各ウィジェットのインスタンス作成後〜メインループ実行前であればどこで実行しても良いです。
# -*- coding:utf-8 -*-
import tkinter
# メインウィンドウ作成
app = tkinter.Tk()
app.geometry("600x400")
# 青色のキャンバス作成
canvas1 = tkinter.Canvas(
app,
width=300,
height=100,
bg="blue"
)
# 緑色のキャンバス作成
canvas2 = tkinter.Canvas(
app,
width=100,
height=200,
bg="green"
)
# 1つ目のボタン作成
button1 = tkinter.Button(
app,
width=10,
height=1,
text="ボタン1"
)
# 2つ目のボタン作成
button2 = tkinter.Button(
app,
width=5,
height=2,
text="ボタン\n2"
)
# ウィジェットの配置
canvas1.grid(
column=0,
row=0
)
button1.grid(
column=1,
row=0,
)
button2.grid(
column=0,
row=1
)
canvas2.grid(
column=1,
row=1
)
# メインループ
app.mainloop()
実行すると下図のようなアプリが起動します。

grid を実行することで親ウィジェットを二次元的にセルに分割し、そのセル内にウィジェットを配置することができます。
上記のスクリプトの場合は、メインウィンドウを下のように 2 x 2 の4つのセルに分割し、さらにそれぞれのセルにウィジェットを配置しています。

grid の設定(引数)
grid メソッド指定時にキーワード引数を指定することで、様々な設定を行うことができます。
ここでは grid メソッドに指定可能な下記のキーワードと、そのキーワードで設定できる内容を説明していきます。
使用例に関しては、grid 実行部分のみを示しています(他の部分はgrid使用例で示したものと同じですので、この点を頭に入れて読んでいただけると助かります)。
# ウィジェットの配置
canvas1.grid(
column=0,
row=0
)
button1.grid(
column=1,
row=0,
)
button2.grid(
column=0,
row=1,
sticky=tkinter.NSEW
)
canvas2.grid(
column=1,
row=1
)
column・row
column・row を指定することで、grid を実行したウィジェットを親ウィジェットのどのセルにウィジェットを配置するかを設定することができます。column・row は “0” 以上の整数を指定します。

また、grid メソッド実行時に指定した column・row の最大値に応じてセルが自動的に分割されます。
具体的には、column で指定した値の中の最大値 +1 の列数に、row で指定した値の中の最大値 +1 の行数に分割されます。
この時、各セルの幅はそのセルの列の中に配置されるウィジェットの中で一番幅が大きいサイズに、各セルの高さはそのセルの行の中に配置されるウィジェットの中で一番高さがが大きいサイズに自動的に調整されます。

ですので、ウィジェットが配置されていないセルのサイズは 0 x 0 になり、見た目的には無い物として扱われます。
各セル全てに配置する必要がなく、下記スクリプトのように column・row を飛び飛びに指定しても OK です。
# ウィジェットの配置
canvas1.grid(
column=0,
row=0
)
button1.grid(
column=2,
row=0,
)
button2.grid(
column=1,
row=1
)
canvas2.grid(
column=3,
row=1
)
このスクリプトを実行して起動するアプリの画面は下のようになります。

sticky
sticky を指定することで、セル内のどの方向にウィジェットを寄せて配置するかを設定することができます。
pack で紹介した anchor 同様に下記のようなパラメータを指定することができます。
tkinter.N:上方向tkinter.S:下方向tkinter.W:左方向tkinter.E:上方向tkinter.NW:左上方向tkinter.NE:右上方向tkinter.SW:左下方向tkinter.SE:右下方向tkinter.CENTER:中央
さらに sticky には下記のパラメータについても指定可能です。
tkinter.NSEW:上下左右
また、sticky には + 演算子を用いて複数の方向を指定することが可能であり、複数指定した場合は各方向に対してウィジェットを引き伸ばすことができます。
sticky に1方向だけ指定する場合の設定例は下記のようになります。
# ウィジェットの配置
canvas1.grid(
column=0,
row=0
)
button1.grid(
column=1,
row=0,
)
button2.grid(
column=0,
row=1,
sticky=tkinter.NE
)
canvas2.grid(
column=1,
row=1
)
この場合、アプリを起動すると下のような画面になります。sticky=tkinter.NE を指定したボタン2が右上方向に寄せられていることが確認できると思います。

sticky に複数の方向を指定する場合の設定例は下記のようになります。
# ウィジェットの配置
canvas1.grid(
column=0,
row=0
)
button1.grid(
column=1,
row=0,
)
button2.grid(
column=0,
row=1,
sticky=tkinter.NE+tkinter.NW+tkinter.S
)
canvas2.grid(
column=1,
row=1
)
この場合、アプリを起動すると下のような画面になります。sticky=tkinter.NE+tkinter.NW+tkinter.S を指定したボタン2がセル内に目一杯に広がっていることが確認できると思います。

この時の sticky の効果を説明しておきます。まずウィジェットは右上方向(tkinter.NE)に配置されます。

さらにそのウィジェットが左上方向(tkinter.NW)に引き伸ばされます。

最後にその引き伸ばされたウィジェットが下方向(tkinter.S)に引き伸ばされ、これによりセル内全体にウィジェットが拡大されたことになります。

sticky に tkinter.NSEW を指定した場合はセル内の全方向にウィジェットが広がることになります。
columnspan・rowspan
columnspan・rowspan を指定することで、複数のセルにまたがってウィジェットを配置することができます。それぞれ正の整数を指定します(0 はダメです)。
columnspanを指定した場合、ウィジェットは column で指定した列から columnspan 列分にまたがって配置されます。
また rowspanを指定した場合、ウィジェットは row で指定した行から columnspan 行分にまたがって配置されます。
columnspan の設定例は下記のようになります。
# -*- coding:utf-8 -*-
import tkinter
# メインウィンドウ作成
app = tkinter.Tk()
app.geometry("200x100")
# 1つ目のボタン作成
button1 = tkinter.Button(
app,
width=10,
height=1,
text="ボタン1"
)
# 2つ目のボタン作成
button2 = tkinter.Button(
app,
width=10,
height=1,
text="ボタン2"
)
# 3つ目のボタン作成
button3 = tkinter.Button(
app,
width=10,
height=1,
text="ボタン3"
)
# ウィジェットの配置
button1.grid(
column=0,
columnspan=2,
row=0,
)
button2.grid(
column=0,
row=1,
)
button3.grid(
column=1,
row=1,
)
# メインループ
app.mainloop()
アプリ起動時の画面は下の図のようになります。

columnspan を指定しない場合はボタン1はボタン2の真上(つまり column=0、row=0)に配置されることになります。
しかし、上のスクリプトではボタン1に columnspan=2 を指定しているので column=0 と column=1 の2列分にまたがって配置され、上の図のようなウィジェットの配置になっています。
こんな感じで columnspan を指定すれば、セルとセルの切れ目の部分にもウィジェットを配置することができます。
また、先ほど説明した sticky を指定すれば、ウィジェットを複数の列全体に広げて配置するようなことも可能です。
複数の列にまたがってウィジェットを配置したい場合はrownspan を指定してください。
padx・pady・ipadx・ipady
padx・pady・ipadx・ipady を grid メソッドに指定することも可能です。
指定の仕方や効果に関しては pack で紹介したものと同様ですので、説明は省略します。
in_
in_ についても pack で紹介したものと同様ですので省略します。
スポンサーリンク
grid 関連のメソッド
grid 関連のメソッドも紹介しておきます。
grid_slaves
コレは便利なので覚えておいた方が良いです!
grid_slaves は実行したウィジェット上に grid で配置されているウィジェットのリストを取得するメソッドです。
引数の column と row により、どこに配置したウィジェットのリストを取得したいかを指定することができます。
例えば下記のようにして grid_slaves を実行することで、frame1 上の column=2, row=1 に配置されたウィジェットのリストを取得することができます。
import tkinter
def button_click():
global frame1
# grid_slavesframe1上の(2, 1)に
# 配置されているウィジェットのリスト取得
widgets = frame1.grid_slaves(column=2, row=1)
# リストの先頭のウィジェットの背景色変更
widgets[0].config(
bg="#FF0000"
)
app = tkinter.Tk()
# フレーム作成と配置
frame1 = tkinter.Frame(
app
)
frame1.pack()
# ボタン作成と配置
button1 = tkinter.Button(
app,
text="ボタン",
command=button_click
)
button1.pack()
# ラベル作成と配置
for j in range(5):
for i in range(3):
# 3x5のラベルを作成してgridで配置
label = tkinter.Label(
frame1,
text="test"
)
label.grid(column=i, row=j)
app.mainloop()
取得したリストからウィジェットを取り出して設定変更などを行うことも可能です。上の例だと背景色を変更しています。
取得できるのはリストである点に注意です。1つしかウィジェットが配置されていない場合でも、要素番号を指定するようにしましょう。
grid_info
grid_info は実行したウィジェットに対する grid の情報を取得するメソッドです。
要は grid メソッド実行時に設定した情報(辞書形式)を取得することができます。
# button1はボタンのインスタンス
info = button1.grid_info()
grid_forget
grid_forget は実行したウィジェットを画面から消すメソッドです。
画面からは消えますが、そのウィジェットのインスタンスが消えるわけではないので再度 grid メソッド等で画面に表示することができます(ただし前回指定した設定は忘れ去られているので再度設定が必要)。
# button1はボタンのインスタンス
button1.grid_forget()
grid_remove
grid_remove は grid_forget 同様に実行したウィジェットを画面から消すメソッドです。
が、grid_remove はgrid_forget とは違って前回 grid メソッド実行時に指定した設定が保持されているので、再度 grid メソッドを実行すれば(引数なしで)前回と同じ設定で画面に配置することができます。
# button1はボタンのインスタンス
button1.grid_remove()
grid_size
grid_size はセルの数を返却するメソッドです。具体的にはセルの行数と列数を返却します。ウィジェットの配置先となる親ウィジェットで実行します。
# appは親ウィジェットのインスタンス
app.grid_size()
grid_anchor
grid_anchor は分割されたセルをどの方向に寄せるかを指定するメソッドです。
packの anchor指定で示した9つのパラメータを指定することができます。
tkinter.N:上方向tkinter.S:下方向tkinter.W:左方向tkinter.E:上方向tkinter.NW:左上方向tkinter.NE:右上方向tkinter.SW:左下方向tkinter.SE:右下方向tkinter.CENTER:中央
grid_anchor はウィジェットの配置先となる親ウィジェットで実行します。
# appは親ウィジェットのインスタンス
app.grid_anchor(tkinter.CENTER)
grid_columnconfigure
grid_columnconfigure は列ごとにセルの設定を行うメソッドです。ウィジェットの配置先となる親ウィジェットで実行します。
第1引数には列番号(grid メソッド実行時に column で指定した値)を、第2引数以降は、下記に記載した設定をキーワード引数により指定します。
weight:- 指定した列のセルをウィンドウの余白量に応じて横方向に広げるかどうかの設定
0:広げない1以上:広げる(値に応じて広がる割合が増加)
- 指定した列のセルをウィンドウの余白量に応じて横方向に広げるかどうかの設定
minsize:- 指定した列のセルの横方向最小サイズ(px)
pad:- 指定した列のセルに対する横方向の余白追加量(px)
ちょっと分かりにくい weight 設定について、下記スクリプトを基に説明したいと思います。
# -*- coding:utf-8 -*-
import tkinter
# メインウィンドウ作成
app = tkinter.Tk()
app.geometry("600x400")
# 青色のキャンバス作成
canvas1 = tkinter.Canvas(
app,
width=100,
height=100,
bg="blue"
)
# 緑色のキャンバス作成
canvas2 = tkinter.Canvas(
app,
width=100,
height=100,
bg="green"
)
# 赤色のキャンバス作成
canvas3 = tkinter.Canvas(
app,
width=100,
height=100,
bg="red"
)
# 紫色のキャンバス作成
canvas4 = tkinter.Canvas(
app,
width=100,
height=100,
bg="purple"
)
# ウィジェットの配置
canvas1.grid(
column=0,
row=0,
sticky=tkinter.NSEW
)
canvas2.grid(
column=1,
row=0,
sticky=tkinter.NSEW
)
canvas3.grid(
column=0,
row=1,
sticky=tkinter.NSEW
)
canvas4.grid(
column=1,
row=1,
sticky=tkinter.NSEW
)
# メインループ
app.mainloop()
実行して起動するアプリの画面は下の図のようになります。

4つのセルに分割され、各ウィジェットに sticky=tkinter.NSEW をしているのでセルいっぱいにウィジェットが引き伸ばされるため、上の図のようなアプリ画面になっています。
続いて下記を mainloop 実行前に追加して grid_columnconfigure により column=0 の列に weight=1 を設定します。
# appはメインウィンドウのインスタンス
app.grid_columnconfigure(0, weight=1)
これを追加することで、アプリの起動画面は下の図のように変わります。もともとメインウィンドウの右側にあった余白量の分、column=0 の列のセルの横方向のサイズが広がっていることが確認できると思います。

column=1 の列のセルの横方向のサイズが変化していないのは weight を設定していないためです(縦方向のサイズを変化させたい場合は次に説明する grid_rowconfigure メソッドを使用します)。
今度は下記のように column=1 に対して weight=2 を設定してみましょう。
# appはメインウィンドウのインスタンス
app.grid_columnconfigure(0, weight=1)
app.grid_columnconfigure(1, weight=2)
この時のアプリの画面は下の図のようになります。

今度は column=1 の列のセルも広がっていることが確認できると思います。column=1 の方がセルが大きくなっているのは、weight で指定した値が column=0 よりも大きいためです。
こんな感じで weight の比率に応じて、その列のセルに与えられる親ウィジェットの余白が増えることになります。
また親ウィジェットの余白量が変われば weight の比率に応じて各列のサイズも変わります。下の図は column=0 と column=1 両方に対して weight=1 を設定したアプリのメインウィンドウを変化した時のアニメになります。

こんな感じで weight を利用することで、ウィンドウのリサイズ時にもレイアウトの崩れないウィジェットの配置が可能になります。
grid_rowconfigure
grid_rowconfigure は行ごとにセルの設定を行うメソッドです。
grid_columnconfigure と設定する方向が異なるだけで使い方等は同じなので説明は省略します。
grid_bbox(bbox)
grid_bbox は引数で指定したセルの親ウィジェット上の左上座標とサイズを返却するメソッドです。ウィジェットの配置先となる親ウィジェットで実行します。
grid_bbox の返却値は (x, y , width, height) の形式のタプルとなります。
x:指定したセルの横方向の座標(親ウィジェット上での座標)y:指定したセルの縦方向の座標(親ウィジェット上での座標)width:指定したセルの横方向のサイズheight:指定したセルの縦方向のサイズ
grid_bbox の定義は下記のようになっており、最大4つの引数を指定することができます。
grid_bbox(self, column=None, row=None, col2=None, row2=None)
1つのセルの座標とサイズを取得したい場合は column と row の2つを指定します。これにより指定した column と row の位置のセルの左上座標とサイズが返却されます。
column・row・col2・row2 の4つの引数を指定することで、複数のセルを指定することも可能です。
この場合は column から col2 の行および row から row2 の列の範囲のセルを合体させた時の座標とサイズを取得することができます。

また、引数を指定しなかった場合は、全ての行と全ての行の範囲のセルを合体させた時の座標とサイズを取得することができます。
ただし grid_bbox はウィジェットの配置が完了し、それが画面に反映された後でなければうまく情報が取得できない点に注意してください。
基本的にウィジェットの配置等が画面に反映されるのは mainloop 実行中や update メソッド実行後になります。このあたりは下記のメインウィンドウのページで解説しているので詳しく知りたい方は読んでみてください。
したがって、mainloop 実行前は update メソッド実行しない限りは grid_bbox を実行してもうまく情報が取得できません。おそらく取得できるデータは (0, 0, 0, 0) になると思います。
grid を使用するメリット・デメリット
簡単にウィジェットを2次元的に配置できる点が良いです。
基本的に GUI アプリではウィジェットを2次元的に配列することになりますので、一番使われている方法ではないかと思います。
ウィジェットの数が多くてもそこまで負荷は増えません。
大雑把にウィジェットを配置する点では最強だと思いますが、細かくウィジェットの位置を指定したい場合は次に説明する place の方が向いていると思います。
place
place は親ウィジェット上の座標を指定して、その座標にウィジェットを配置するメソッドです。
スポンサーリンク
place 使用例
place を使用してウィジェットを配置するサンプルスクリプトは下記のようになります。place を最後にまとめて実行していますが、これは今後の説明をしやすくするためです。
各ウィジェットのインスタンス作成後〜メインループ実行前であればどこで実行しても良いです。
# -*- coding:utf-8 -*-
import tkinter
# メインウィンドウ作成
app = tkinter.Tk()
app.geometry("600x400")
# 青色のキャンバス作成
canvas1 = tkinter.Canvas(
app,
width=100,
height=50,
bg="blue"
)
# 緑色のキャンバス作成
canvas2 = tkinter.Canvas(
app,
width=50,
height=100,
bg="green"
)
# 1つ目のボタン作成
button1 = tkinter.Button(
app,
width=10,
height=1,
text="ボタン1"
)
# 2つ目のボタン作成
button2 = tkinter.Button(
app,
width=5,
height=2,
text="ボタン\n2"
)
# 各ウィジェットの配置
canvas1.place(
x=100,
y=100
)
button1.place(
x=400,
y=100
)
button2.place(
x=100,
y=200
)
canvas2.place(
x=400,
y=200
)
# メインループ
app.mainloop()
実行すると下図のようなアプリが起動します。

place は考え方は最もシンプルで、place を実行することで、引数で指定した(x , y) 座標にウィジェットが配置されます。

原点は親ウィジェットの左上端で、x 軸の正方向は右、y 軸の正方向は下になります。
place の設定(引数)
place メソッド指定時にキーワード引数を指定することで、様々な設定を行うことができます。
ここでは place メソッドに指定可能な下記キーワードと、そのキーワードで設定できる内容を説明していきます。
使用例に関しては、place 実行部分のみを示しています(他の部分はplace使用例で示したものと同じですので、この点を頭に入れて読んでいただけると助かります)。
# 各ウィジェットの配置
canvas1.place(
x=100,
y=100
)
button1.place(
x=400,
y=100
)
button2.place(
x=100,
y=200
)
canvas2.place(
x=400,
y=200
)
x・y
x・y を指定することで、ウィジェットを配置する座標を設定することができます。
ウィジェットの左上を基準に、親ウィジェットの(x, y)座標にウィジェットが配置されます(どこを基準にするかは次に説明する anchor で指定可能です)。
anchor
anchor を指定することで、ウィジェット配置時のウィジェットの基準位置を指定することができます。
anchor に指定できるパラメータは Pack の anchor で示した9種類と同じになります(デフォルトは tkinter.NW)。
例えば anchor=tkinter.CENTER を指定すれば、親ウィジェットの(x, y)座標にウィジェットの中心が来るようにウィジェットの配置が行われます。
anchor の設定例は下記のようになります。
# 各ウィジェットの配置
canvas1.place(
x=100,
y=100,
anchor=tkinter.CENTER
)
button1.place(
x=400,
y=100,
anchor=tkinter.NW
)
button2.place(
x=100,
y=200,
anchor=tkinter.S
)
canvas2.place(
x=400,
y=200,
anchor=tkinter.SE
)
スクリプトを実行して起動するアプリの画面は下図のようになります。

width・height
width・height を指定することで、ウィジェットの幅と高さを指定することができます。
ピクセル単位で指定します。
place メソッドに width・height を指定することで、ウィジェットのインスタンス作成時に指定した width・height は無視されるので注意しましょう。
width・height の設定例は下記のようになります。
# 各ウィジェットの配置
canvas1.place(
x=100,
y=100,
width=100,
height=100
)
button1.place(
x=400,
y=100,
width=100,
height=100
)
button2.place(
x=100,
y=200,
width=100,
height=100
)
canvas2.place(
x=400,
y=200,
width=100,
height=100
)
スクリプトを実行して起動するアプリの画面は下図のようになります。
各ウィジェットの幅と高さは、ウィジェットインスタンス時に指定した width・height ではなく、place メソッド実行時に指定した width・height になってることも確認できると思います。

relx・rely
relx・rely は x・y 同様にウィジェットを配置する座標を指定する引数になります。
ですが、 x・y は親ウィジェット上の座標を単純に指定するのに対し、relx・rely は親ウィジェットの幅と高さを “1” とした時の相対位置を指定する点が異なります。

例えば親ウィジェットの中心は relx=0.5・rely=0.5 になります。
指定できる値は 0.0 〜 1.0 になります。
relx・rely の設定例は下記のようになります。
# 各ウィジェットの配置
canvas1.place(
relx=0.1,
rely=0.1
)
button1.place(
relx=0.6,
rely=0.1
)
button2.place(
relx=0.1,
rely=0.6
)
canvas2.place(
relx=0.6,
rely=0.6
)
スクリプトを実行して起動するアプリの画面は下図のようになります。

前述の通り、relx・rely は親ウィジェットの幅と高さを “1” とした時の相対位置となりますので、親ウィジェットのサイズが変わればそれに応じてウィジェットの配置位置も変化する点もポイントです。

relwidth・relheight
relwidth・relheight は width・height 同様にウィジェットの幅と高さを指定する引数になります。
ですが、 width・height はピクセル単位で指定するするのに対し、relwidth・relheight は親ウィジェットの幅と高さを “1” とした時の相対的なサイズを指定する点が異なります。

例えば親ウィジェットの幅と高さそれぞれの半分のサイズを表す場合は relwidth=0.5・relheight=0.5 になります。
指定できる値は 0.0 〜 1.0 になります。
relwidth・relheight の設定例は下記のようになります。
# 各ウィジェットの配置
canvas1.place(
relx=0.1,
rely=0.1,
relwidth=0.3,
relheight=0.3
)
button1.place(
relx=0.6,
rely=0.1,
relwidth=0.3,
relheight=0.3
)
button2.place(
relx=0.1,
rely=0.6,
relwidth=0.3,
relheight=0.3
)
canvas2.place(
relx=0.6,
rely=0.6,
relwidth=0.3,
relheight=0.3
)
スクリプトを実行して起動するアプリの画面は下図のようになります。

前述の通り、relwidth・relheight は親ウィジェットの幅と高さを “1” とした時の相対サイズとなりますので、親ウィジェットのサイズが変わればそれに応じてウィジェットの幅と高さも変化する点もポイントです。
上記スクリプトではウィジェットの位置も相対位置である relx・rely を指定しているため、ウィジェットの位置も幅・高さも親ウィジェットのサイズに応じて変化します。
なので親ウィジェットのサイズ変更によるレイアウトの崩れはありません(文字のサイズなどのウィジェットの中身は別途リサイズ対応が必要)。

bordermode
bordermode を指定することで、ウィジェットを配置する親ウィジェットの基準位置、つまり(0, 0)座標を「外枠の外側」にするか「外枠の内側」にするかを指定することができます。
bordermode に指定するパラメータは下記の2つになります。
tkinter.INSIDE:ウィジェットを配置する親ウィジェットの基準位置を「外枠の内側」とするtkinter.OUTSIDE:ウィジェットを配置する親ウィジェットの基準位置を「外枠の外側」とする
bordermode の設定例は下記のようになります(今回の例は他の例と作成するウィジェットが異なるのでスクリプト全体を載せています)。
# -*- coding:utf-8 -*-
import tkinter
# メインウィンドウ作成
app = tkinter.Tk()
app.geometry("600x400")
# フレーム作成
frame1 = tkinter.Frame(
app,
width=600,
height=400,
borderwidth=30,
bg="yellow",
relief=tkinter.SUNKEN
)
# 緑色のキャンバス作成
canvas1 = tkinter.Canvas(
frame1,
width=50,
height=100,
bg="green"
)
frame1.pack()
# 各ウィジェットの配置
canvas1.place(
relx=0,
rely=0,
bordermode=tkinter.INSIDE
)
# メインループ
app.mainloop()
緑色のキャンバスの place 実行時に bordermode=tkinter.INSIDE を指定しているので、親ウィジェットの外枠の内側を基準位置として指定した位置(0, 0)に配置されていることが確認できると思います。

bordermode の指定部分のみを bordermode=tkinter.OUTSIDE に変更した場合のアプリ画面は下のようになります。

今度は親ウィジェットの外枠の外側を基準位置として指定した位置(0, 0)に配置されていることが確認できると思います。
in_
in_ を指定することで、ウィジェットの配置先となる親ウィジェットを設定することができます。
place 関連のメソッド
place 関連のメソッドも紹介しておきます。
place_info
place_info は実行したウィジェットに対する place の情報を取得するメソッドです。
要は place メソッド実行時に設定した情報(辞書形式)を取得することができます。
# button1はボタンのインスタンス
info = button1.place_info()
place_forget
place_forget は実行したウィジェットを画面から消すメソッドです。
画面からは消えますが、そのウィジェットのインスタンスが消えるわけではないので再度 place メソッド等で画面に表示することができます(ただし前回指定した設定は忘れ去られているので再度設定が必要)。
# button1はボタンのインスタンス
button1.place_forget()
スポンサーリンク
place を使用するメリット・デメリット
考え方は一番シンプルだと思います。私はこの方法が一番好きですね。一番ウィジェットの位置を細かく指定できる方法でもあります。
ただし座標を指定する必要があるので座標を計算するのが大変です。
特にウィジェットの数が多ければ多いほど座標を計算する負荷が増えます。
まとめ
このページでは Tkinter でのウィジェットの配置について説明しました。
配置するために利用するメソッドには下記の3種類があります。それぞれ特徴が異なるのでこの特徴だけはしっかり覚えておきましょう!
pack:ウィジェットをある方向にどんどん詰め込むgrid:2次元的に親ウィジェットをセルに分割し、セル内にウィジェットを配置するplace:配置する座標を指定してウィジェットを配置する
用途としては、とにかくウィジェットを配置したいだけなら pack、簡単にウィジェットを2次元的に配置したいなら grid、座標計算が得意な人は place といった感じかなあと思います。
また、各メソッド実行時には様々な引数が指定可能であり、細やかな設定を行うことができます。各メソッドに対して指定可能な全引数をこのページでまとめていますので、困ったときに参照していただければと思います!

