かなり間があきましたが、今回は「いまさらpython学習」の5回目です。前回はざっくりボタンやテキストボックスなどのウィジェットを適当に配置し、GUIプログラミングを体験してみました。今回は、少しまともにレイアウトを考えてみたいと思います。
レイアウトをおこなうためには、pack・grid・place というメソッドが利用できるようです。簡単に説明しておくと、pack は 縦もしくは横に単純にウィジェット並べていく(順に詰め込んでいく)ようなイメージのレイアウトになります。grid は 表形式でウィジェットを配置していくイメージです。HTMLのtableタグや、エクセルなどを思い浮かべてもらってそのマスにウィジェットを配置していくイメージです。placeは、指定個所にウィジェットを配置していきます。
前回の記事はこちら
メリット・デメリット
それぞれのメソッドのメリット、デメリットは以下のような感じ。今回(このブログ)は、gridを採用(多用)していきたいと思いますので、gridについて、記載していきます。
pack
メリット:他の2つに比べてない?(一番簡単といわれているが・・・。)
デメリット:1次元(1列または1行)でしか配置できない。
grid
メリット:全ウィジェットの座標を把握しなくても、ざっくりできれいに配置できる。
デメリット:細かい配置は難しい(隣接するのセルの大きさに影響されズレが生じる)
https://tkdocs.com/tutorial/grid.html
place
メリット:指定個所に配置できるので、レイアウトを細かく指定できる
デメリット:全ウィジェットの座標を把握しておく必要があり、再配置の時などはかなり手間となる
grid
さて前述の通り、本ブログでは、grid を紹介していこうと思います。gridは、行・列(表)でウィジェット配置していきます。
4回目で適当にウィジェットを配置した、以下のウィンドウを修正していこうと思います。
とりあえず、配置する行列を指定
grid で行列配置するには、 row、column を利用して、配置する行列の位置を指定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | import tkinter main = tkinter.Tk() main.title("Hello Tkinter") main.geometry("300x300") text = tkinter.Label(main, text="Hello python.") text.grid(row=0, column=0) btn = tkinter.Button(main, text="Click ME!") btn.grid(row=1, column=1) txtbox = tkinter.Entry(main,width=30) txtbox.grid(row=1, column=0) rbtn1 = tkinter.Radiobutton(main, text='select 1') rbtn1.grid(row=2, column=0) rbtn2 = tkinter.Radiobutton(main, text='select 2') rbtn2.grid(row=2,column=1) rbtn3 = tkinter.Radiobutton(main, text='select 3') rbtn3.grid(row=2,column=2) chbox = tkinter.Checkbutton(main, text='Check ME!') chbox.grid(row=3,column=0) main.mainloop() |
row、column で配置する行列の位置を指定していますが、やったことがある方は、すぐにこのコードは変だと気付くと思います。以下のような「くずれた」レイアウトになります。
行毎の列数(列毎の行数)が等しくなるように配置
先ほどの例に対して、行や列をまたがせて、綺麗に4行3列になるようにしてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | import tkinter main = tkinter.Tk() main.title("Hello Tkinter") main.geometry("300x300") text = tkinter.Label(main, text="Hello python.") text.grid(row=0, column=0,columnspan=3) btn = tkinter.Button(main, text="Click ME!") btn.grid(row=1, column=2) txtbox = tkinter.Entry(main,width=30) txtbox.grid(row=1, column=0,columnspan=2) rbtn1 = tkinter.Radiobutton(main, text='select 1') rbtn1.grid(row=2, column=0) rbtn2 = tkinter.Radiobutton(main, text='select 2') rbtn2.grid(row=2,column=1) rbtn3 = tkinter.Radiobutton(main, text='select 3') rbtn3.grid(row=2,column=2) chbox = tkinter.Checkbutton(main, text='Check ME!') chbox.grid(row=3,column=0,columnspan=3) main.mainloop() |
列をまたぎたい場合は、columnspan を利用します。(行をまたぎたい場合は、rowspan を利用します。)「またぐ」とは、エクセルでいうセルの結合をイメージしてもらうとわかりやすいと思います。それぞれ、またぎたい数を指定します。これで、それなりに整ってきました。
左に寄せ右寄せを使う
3列に跨がせたので、一番上のテキスト「Hello python.」が中央よりになってしまっています。これを左寄せにして、ついでにチェックボックスの「Click ME!」右寄せにしてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | import tkinter main = tkinter.Tk() main.title("Hello Tkinter") main.geometry("300x300") text = tkinter.Label(main, text="Hello python.") text.grid(row=0, column=0,columnspan=3,sticky=tkinter.W) btn = tkinter.Button(main, text="Click ME!") btn.grid(row=1, column=2) txtbox = tkinter.Entry(main,width=30) txtbox.grid(row=1, column=0,columnspan=2) rbtn1 = tkinter.Radiobutton(main, text='select 1') rbtn1.grid(row=2, column=0) rbtn2 = tkinter.Radiobutton(main, text='select 2') rbtn2.grid(row=2,column=1) rbtn3 = tkinter.Radiobutton(main, text='select 3') rbtn3.grid(row=2,column=2) chbox = tkinter.Checkbutton(main, text='Check ME!') chbox.grid(row=3,column=0,columnspan=3,sticky=tkinter.E) main.mainloop() |
右寄せ左寄せには、sticky を使います。それぞれ、左右によりましたね。
tkinter.CENTER(中)、tkinter.W(左)、tkinter.E(右)、tkinter.N(上)、tkinter.S(下)、tkinter.NW(左上)、tkinter.NE(右上)、tkinter.SW(左下)、tkinter.SE(右下) です。
また、引き伸ばしの指定ができて、
tkinter.W + tkinter.E で左右に引き伸ばし、tkinter.N + tkinter.S で上下に引き伸ばせます。
tkinter.W + tkinter.E + tkinter.N + tkinter.S で全体に引き伸ばせます。
隙間をあける
気になった方も多いと思いますが、左側がウィンドウ枠ぎりぎりにくっついていて少し見苦しいです。隙間をあけてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | import tkinter main = tkinter.Tk() main.title("Hello Tkinter") main.geometry("300x300") text = tkinter.Label(main, text="Hello python.") text.grid(row=0, column=0,columnspan=3,padx=10,pady=5,sticky=tkinter.W) btn = tkinter.Button(main, text="Click ME!") btn.grid(row=1, column=2,padx=10) txtbox = tkinter.Entry(main,width=30) txtbox.grid(row=1, column=0,columnspan=2,padx=10) rbtn1 = tkinter.Radiobutton(main, text='select 1') rbtn1.grid(row=2, column=0,pady=5) rbtn2 = tkinter.Radiobutton(main, text='select 2') rbtn2.grid(row=2,column=1) rbtn3 = tkinter.Radiobutton(main, text='select 3') rbtn3.grid(row=2,column=2) chbox = tkinter.Checkbutton(main, text='Check ME!') chbox.grid(row=3,column=0,columnspan=3,sticky=tkinter.E) main.mainloop() |
隙間をあけるには、padx、pady を使います。
これで、それっぽく配置できました。
おわりに
先ほどのウィンドウでも、若干 select2 の位置がズレているように見えたと思います。これは、2行目のEntry(テキストボックス)の長さが長く、1,2列めと3列目の幅が等間隔にならず、ズレが生じています。少しEntry(テキストボックス)の長さを短くするか、さらにこだわって綺麗に配置したい場合は、place を使うのがよさそうです。width=25 とするとこんな感じになりました。