Tkinter GUIアプリケーションの部品 (widgets) をウィンドウ上にどうやって配置するのだろう - 3つのジオメトリマネージャー

Tkinter には3つの 'geometry magagers' がある。

  • grid()

  widget を2次元に配置する。(格子状に配置する。)

  • pack()

  widget を横一列、縦一列に配置する。grid()のように格子状に配置することは苦手。

  • place()

  widget の位置、大きさ、他のwidgetとの位置関係を直接指定して配置する。


grid ジオメトリマネージャー
 widget を作っても 'geometry manager' で配置しないと widget は現れない。そのような訳で以下のふたつのステップで widget を配置する。

thing = Constructor(master , ...)
thing.grid(...)

Constructor とは Button, Frame といった widget クラス。master とはこの widget を作った時の親 widget。全ての widget が grid() メソッドで配置できる。

widget w を画面に表示するには以下のようにする。

w.grid(option, ...)

このようにジオメトリーマネージャーで widget を配置するまでは内部的には存在するが画面には現れない。

grid ジオメトリマネージャーのオプション

column widget を配置する列番号。0からカウント。デフォルトは0。
row widget を配置する行番号。0からカウント。デフォルトは次にあいている行番号。
columnspan 通常 widget はひとつのセルを占有するが、いくつかの列をくっつけてひとつの大きなセルとすることも出来る。例えば、w.grid(row0,column2,columnspan=3) とした場合 widget w は0行目の2列目、3列目、4列目に配置される。
rowspan 通常 widget はひとつのセルを占有するが、いくつかの行をくっつけてひとつの大きなセルとすることも出来る。例えば、w.grid(row=3,column=2,rowspan=4,columnspan=5) とした場合 widget w は 行3-6 、列2-6 の20セルが連結される。
ipadx 内側の横の隙間を指定します。
ipady 内側の縦の隙間を指定します。
padx 外側の横の隙間を指定します。
pady 外側の縦の隙間を指定します。
sticky sticky オプションを指定しなかった場合 widget は中央に配置される。widget を角に配置したい場合は 1.右上: sticky=NE 2.右下: sticky=SE 3.左下: sticky=SW 4.左上: sticky=NWとする。sticky=N+S とすると上下に伸びて左右中央に配置される。sticky=E+W とすると左右に伸びて上下中央に配置される。sticky=N+E+S+W とするとセルの上下左右を埋めるように配置される。sticky=N+S+W とすると上下に伸びて左側に配置される。

NW
N
NE
W CENTER E
SW
S
SE


こんな感じに配置する場合は・・・


# -*- coding: utf-8 -*-

from Tkinter import *

root = Tk()

button1=Button(root,text='BUTTON1')
button1.grid(column=1,row=0)

button2=Button(root,text='BUTTON2')
button2.grid(column=0,row=1)

mainloop()



ボタンを三つにしてみてこんな感じに配置する場合は・・・


# -*- coding: utf-8 -*-

from Tkinter import *

root = Tk()

button1=Button(root,text='BUTTON1')
button1.grid(column=1,row=0)

button2=Button(root,text='BUTTON2')
button2.grid(column=0,row=1)

button3=Button(root,text='BUTTON3')
button3.grid(column=1,row=1)

mainloop()



BUTTON3の周りに隙間を作ってみる。



# -*- coding: utf-8 -*-

from Tkinter import *

root = Tk()

button1=Button(root,text='BUTTON1')
button1.grid(column=1,row=0)

button2=Button(root,text='BUTTON2')
button2.grid(column=0,row=1)

button3=Button(root,text='BUTTON3')
button3.grid(column=1,row=1,padx=10,pady=10)

mainloop()


その他の grid 管理メソッド
これらの grid 関連のメソッドは全ての widget で利用できる。

  • w.grid_forget()

 このメソッドは widget w を画面から見えなくする。見えなくするだけでまだ存在はする。もう一度 .grid() とすることで再度見えるように出来るが以前指定したオプションは保持していない。

  • w.grid_remove()

 w.grid_forget() と似ているが、違う点はオプションを保持しているところ。.grid() とすれば再度以前に指定したオプション設定で画面上に現れる。

  • w.grid_propagate()

 通常 widget はコンテンツにあわせて大きくなる。しかしコンテンツのサイズに関わらず widget の大きさを指定したい場合は w.grid_propagate(0) としてサイズを指定する。


行と列のサイズを再構成する。
 何か特別なことをしなければ widget の幅と高さは配置された時の幅と高さのままである。
 以下のメソッドを使うと行と列のサイズ調整を再構成(override)できる。

w.columnconfigure(n, option=value, ...)
w.rowconfigure(n, option=value, ...)

w は再構成したいwidget 、n は再構成したい行か列番号、option は以下を参照。

minsize 行や列の最小サイズ。ピクセル単位で指定。
pad セルとその中の widget の間の余白。ピクセル単位で指定
weight 行や列が伸びた時に widget が伸びる比率。







 以下の例は横方向にウィンドウを150ピクセル大きくすると、0列目(青と赤)は50ピクセル1列目(黄色)は100ピクセル大きくなる。

# -*- coding: utf-8 -*-

from Tkinter import *

root = Tk()

lab1=Label(root,text='LABEL1',bg='blue')
lab1.grid(row=0,column=0,sticky='news')

lab2=Label(root,text='LABEL2',bg='yellow')
lab2.grid(row=0,column=1,sticky='news')

lab3=Label(root,text='LABEL3',bg='red')
lab3.grid(row=2,column=0,sticky='news')

root.grid_columnconfigure(0,weight=1)
root.grid_columnconfigure(1,weight=2)

root.mainloop()


pack ジオメトリマネージャー
 .pack() メソッドは横一列もしくは縦一列に widget を配置する。.grid() メソッドのように格子状に widget を配置することは苦手。

w.pack(option, ...)

w は widget 、option は以下参照。

side TOP 上から順番に配置していく。LEFT 左から順番に配置していく。BOTTOM 下から順番に配置していく。RIGHT 右から順番に配置していく。 上の四種類を混ぜて使うことも出来るが期待した配置にならないことがある。格子状に配置したいのであれば .grid() を使うかもしくは、入れ子状にしたフレームを駆使して .pack() を使う。
fill  widget は pack() した時点で与えられたスペースを一杯に使って表示される。その後、親 widget のサイズが変更された時に BOTH を指定すると幅高さ共に親 widget にあわせてサイズ変更する。X を指定した場合は幅を、Y を指定した場合は高さを親 widget に合わせてサイズ変更する。デフォルトは親 widget に合わせてサイズ変更しない NONE である。
expand  0 を指定すると親 widget がサイズ変更された時にもサイズを合わせて変更しない。(0が規定値) 1 を指定すると親 widget がサイズ変更されるとそれに合わせてサイズを変更する。
in もしくは in_  親 widget を指定する。widget入れ子状にする時に使用。 in は python予約語であるので python で Tkを使う場合は in_ アンダースコアをつけて使用する。
padx 外側の横の隙間を指定します。
pady 外側の縦の隙間を指定します。
ipadx 内側の横の隙間を指定します。
ipady 内側の縦の隙間を指定します。


上から順番に配置してみる。




# -*- coding: utf-8 -*-

from Tkinter import *

root = Tk()

lab1=Label(root,text='LABEL1',bg='yellow')
lab1.pack(side=TOP)

lab2=Label(root,text='LABEL2',bg='white')
lab2.pack(side=TOP)

lab3=Label(root,text='LABEL3',bg='red')
lab3.pack(side=TOP)

lab4=Label(root,text='LABEL4',bg='green')
lab4.pack(side=TOP)

lab5=Label(root,text='LABEL5',bg='blue')
lab5.pack(side=TOP)

root.mainloop()



左から順番に並べてみる。

# -*- coding: utf-8 -*-

from Tkinter import *

root = Tk()

lab1=Label(root,text='LABEL1',bg='yellow')
lab1.pack(side=LEFT)

lab2=Label(root,text='LABEL2',bg='white')
lab2.pack(side=LEFT)

lab3=Label(root,text='LABEL3',bg='red')
lab3.pack(side=LEFT)

lab4=Label(root,text='LABEL4',bg='green')
lab4.pack(side=LEFT)

lab5=Label(root,text='LABEL5',bg='blue')
lab5.pack(side=LEFT)

root.mainloop()



widget がサイズ変更されるとそれに合わせてサイズを変更する。




# -*- coding: utf-8 -*-

from Tkinter import *

root = Tk()

lab1=Label(root,text='LABEL1',bg='yellow')
lab1.pack(side=TOP,fill=BOTH,expand=1)

root.mainloop()



widget がサイズ変更されるとそれに合わせて縦方向だけサイズを変更する。





# -*- coding: utf-8 -*-

from Tkinter import *

root = Tk()

lab1=Label(root,text='LABEL1',bg='yellow')
lab1.pack(side=TOP,fill=Y,expand=1)

root.mainloop()


その他の pack 管理メソッド

  • w.pack_propagate(value)

配置情報を伝播するかどうか。0, on の場合は伝播する。1, off の場合は伝播しない。

  • w.pack_slaves()

従属している widget をリストで返す。

  • w.pack_configure(option=value, ...)

option を指定する。

  • w.pack_forget()

 このメソッドは widget w を画面から見えなくする。見えなくするだけでまだ存在はする。pack() もしくは他のジオメトリマネージャーで配置することで再度見えるように出来るが以前指定したオプションは保持していない。

  • w.pack_info()

現在の option の状況を dictionary で返す。