今回は、pythonのGUIライブラリ「tkinter」についてです。
tkinterでは、Widget(ウィジェット)と呼ばれるパーツを組み合わせて、GUIを作っていきます。
この記事では、「tkinter を使ったパーツの配置方法」をご紹介します。
この記事を読めば、
- Widgetとは何か
- Widgetを配置する3つの方法
を理解し、実装できるようになれます。
それでは、よろしくお願いします。
tkinterのWidgetとは
tkinter は python にデフォルトで入っている、GUIライブラリです。
※tkinter の基礎については、下記記事をご参考ください。
Widget(ウィジェット)とは、GUIで画面を構成するパーツのことです。
例えば、、、
① ラベル…文字を表示する
② ボタン…クリックできるやつ
③ テキストボックス…文字を入力できる
④ コンボボックス…選択肢から選べる
⑤ キャンバス…図や写真などを表示する
:
などがあります。
tkinterで作られる画面は、これらのWidgetで構成されています。
下記が、 tkinter で作ったGUIアプリの例です。
身近なソフトでも、よくある画面かと思います。
※ExcelのVBAなどでも同じようなパーツがありますね。
次に、これらWidgetの配置方法をご紹介します。
Widget配置方法
前節で説明したWidgetオブジェクトには、それを配置するメソッドが備わっています。
Widgetを配置するメソッドは、下記の3つです。
- place…ピンポイントで配置
- pack…縦or横に整列して配置
- grid…EXCELのようにマス目(grid)状に配置
サンプルプログラム
下記プログラムは、ボタンを生成した後に、それをplaceメソッドで配置している例です。
import tkinter root = tkinter.Tk() #tkinterのGUIオブジェクト生成 button = tkinter.Button(root, text = "ただのボタン") #ボタンWidgetを生成 button.place(x=5, y=5) #ボタンを配置 root.mainloop() #イベントループ
■実行結果
■解説
1行目、3行目、8行目はtkinterお約束の処理です。
※補足(読み飛ばしてもOK)
1行目でtkinterのライブラリを読み込み、3行目でtkinterのルートオブジェクトを生成しています。
プログラム実行結果の大枠がこのオブジェクトに該当します。
このオブジェクトの中にWidgetを配置して画面を作ります。
8行目では、画面を表示させ続けてイベント処理を捕捉するために必要な処理です。
サンプルプログラムの4行目でボタンのWidgetを生成していますが、この行だけでは配置されません。
5行目ように、placeメソッドを呼ぶことで、画面上にボタンが表示されます。
このように、
- Widgetオブジェクトを生成
- 配置メソッド(place、pack、gridのどれか)を呼ぶ
という、流れになります。
次は3つの配置方法を学びましょう。
その1『place』…ピンポイントで位置を指定
placeメソッドは、下記イメージのように、Widgetの位置を座標的に指定して配置できます。
下記のオプションが指定可能です。
オプション
・anchor
他のオプションで、位置を指定する際の基準点のオプションです。
イメージでは赤の星マーク★に該当します。
tkinter.N(上)、tkinter.E(右)、tkinter.S(下)、tkinter.W(左)、tkinter.NE(右上)、tkinter.NW(左上)、tkinter.SE(右下)、tkinter.SW(左下)、tkinter.CENTER(中央)があります。
デフォルトはNW。
※N、E、S、Wはそれぞれ方角(North、East、South、West)に由来。
・bordermode
他のオプションで、位置を指定する際に、親ウィジェットの境界線の内側からカウントするか、外側からカウントするかのオプションです。
INSIDE(内側からカウント)とOUTSIDE(外側からカウント)があります。
デフォルトはINSIDE。
・height, width
ウィジェットの大きさを指定するオプション。
ピクセル単位で高さ(height)、幅(width)を指定します。
・relheight, relwidth
ウィジェットの大きさを指定するオプション。
親フレームとの相対長さで、高さ(relheight)、幅(relwidth)を指定します。
0.0から1.0の範囲で指定します。
・x, y
ウィジェットの位置を指定するオプション。
ピクセル単位で横(x)、縦(y)を指定します。
・relx, rely
ウィジェットの位置を指定するオプション。
親フレームとの相対位置で横(relx)、縦(rely)を指定します。
0.0から1.0の範囲で指定します。
※x, y, relx, rely のいずれか一つ以上を選択しなければ、配置されません。
サンプルプログラム
placeメソッドを使用して、ラベルとボタンを配置したサンプルプログラムです。
import tkinter as tk from tkinter import messagebox root = tk.Tk() #tkinterのGUIオブジェクト生成 root.title("Place") root.geometry("200x150") #ウィンドウサイズを指定 label = tk.Label(root, text = "label") #ラベルWidgetを生成 label.place(relx = 0.3, rely = 0.1) #ラベルを配置 button = tk.Button(root, text="Button", command = lambda : tk.messagebox.showinfo("msg", "Do Not Push")) #ボタンWidgetを生成 button.place(x=120, y=80, relheight = 0.2, relwidth = 0.4, anchor=tk.SE) #ボタンを配置 root.mainloop() #イベントループ
■実行結果
ボタンを押すと、次のポップアップが表示されるようにしています。
■解説
8行目、9行目では、ラベルのオブジェクト生成と配置をしています。
x,y座標は親フレームとの相対位置で指定しています。anchorオプションは指定していないので、基準点はNW(左上)となります。
11行目、12行目では、ボタンのオブジェクト生成と配置をしています。
基準点はSE(右下)で、x,y座標はピクセルで指定しています。ウィジェットの大きさは親フレームとの相対長さで指定しています。
11行目でボタンの引数 command では、ボタンを押下したときの処理として、ポップアップを表示するようにしています。
その2『pack』…縦or横に整列して配置
packメソッドは、Widgetを縦方向または横方向に1列に配置する際に使用します。
下記のオプションが指定可能です。
オプション
・anchor
イメージの「ウィジェット②」のようにスペースがある場合、どの方向に寄せるかを指定します。
デフォルトはCENTER。
指定する変数は、placeメソッドと同様です。
・expand
親ウィジェットが広がった場合に、親ウィジェットに合わせて広げるかを指定します。
bool型で指定。True (=1) (広げる)、Faulse (=0) (広げない)。
デフォルトはFaulse (0)。
・fill
スペースがある場合、親ウィジェットに合わせてスペースを埋める(ウィジェットを広げる)かを指定します。
tkinter.NONE(オリジナルサイズを保持)、tkinter.X(X方向:横 に広げる)、tkinter.Y(Y方向:縦 に広げる)、tkinter.BOTH(XY方向:縦横 に広げる)があります。
デフォルトはNONE。
・ipadx, ipady
内側のパディングの幅(ipadx:横方向、ipady:縦方向)を指定。
・padx, pady
外側のパディングの幅(padx:横方向、pady:縦方向)を指定。
・side
イメージの矢印の方向。どの方向から配置をするかを指定。
tkinter.TOP(上から)、tkinter.LEFT(左から)、tkinter.BOTTOM(下から)、tkinter.RIGHT(右から)があります。
デフォルトはTOP。
サンプルプログラム
packメソッドで、ラベルとテキストボックスを配置するサンプルプログラムです。
import tkinter as tk root = tk.Tk() #tkinterのGUIオブジェクト生成 root.title("Pack") #タイトルを指定 root.geometry("400x150") #ウィンドウサイズを指定 label1 = tk.Label(root, text = "テキスト1") #ラベルWidget1を生成 label1.pack() #ラベル1を配置 textBox1 = tk.Entry(root) #テキストボックスWidget1を生成 textBox1.pack() #テキストボックス1を配置 label2 = tk.Label(root, text = "テキスト2") #ラベルWidget2を生成 label2.pack() #ラベル2を配置 textBox2 = tk.Entry(root) #テキストボックスWidget2を生成 textBox2.pack(expand = 1, fill = tk.BOTH, padx = 10, pady = 10) #テキストボックス2を配置 root.mainloop() #イベントループ
■実行結果
もちろん、テキストボックスに記入できます。
■解説
ラベルの生成と配置は7,8行目、13,14行目でしています。
テキストボックスの生成と配置は10,11行目、16,17行目でしています。
2つ目のテキストボックスは fill オプションを有効に(fill = BOTH)しているため、テキストボックスが外枠に合わせて伸びています。
更に、2つ目のテキストボックスは、expand オプションが有効に(expand = 1)なっているため、ウィンドウサイズを大きくしてみると下記のようにテキストボックスも一緒に大きくなります。
その3『grid』…EXCELのようにマス目状に配置
gridメソッドは、Widgetを縦と横のマス目状に配置する際に使用します。
行(row)と列(column)を指定し、ウィジェットを配置するイメージです。
下記オプションが指定可能です。
オプション
・row
Widgetを挿入する行を指定しています。(イメージを参照)
0始まりで、デフォルトは0。
・rowspan
Widgetが複数の行にまたがる場合、このオプションに行数を指定します。
EXCELの行の結合のイメージです。
上記のイメージでは「ウィジェット③」、「ウィジェット⑥」が2行にまたがっている例です。
デフォルトは1。
・column
Widgetを挿入する列をしていします。(イメージを参照)
0始まりで、デフォルトは0。
・columnspan
Widgetが複数の列にまたがる場合、このオプションに列数を指定します。
EXCELの列の結合のイメージです。
上記のイメージでは「ウィジェット①」、「ウィジェット⑧」が2列にまたがっている例です。
デフォルトは1。
・in
指定されたフレーム(親の内部)の内側にウィジェットを配置するオプション。
デフォルトは親フレーム。
・ipadx, ipady, padx, pady
パディングの幅を指定するオプション。
packと同様のため説明省略。
・sticky
セルがWidgetよりも大きい場合、Widgetを展開する方法を定義します。
anchorと同様に、tkinter.N(上)、tkinter.E(右)、tkinter.S(下)、tkinter.W(左)、tkinter.NE(右上)、tkinter.NW(左上)、tkinter.SE(右下)、tkinter.SW(左下)、tkinter.CENTER(中央)を使用し、セルのどこにWidgetをそろえるか指定します。
また、その組み合わせ(N+Sなど)でセルに合わせてWidgetを引き伸ばす方向を指定できます。
例1)NはWidgetをセルの上の境界に揃える。NEはセルの右上に揃える。
例2)N+Sは上下に引き伸ばす。W+E+N+Sは上下左右に引き伸ばす。
サンプルプログラム
gridメソッドで、ラベル、テキストボックス、ボタンを並べたサンプルプログラムです。
import tkinter as tk root = tk.Tk() #tkinterのGUIオブジェクト生成 root.title("grid") #タイトルを指定 label = tk.Label(root, text = "テキスト1") #ラベルWidget1を生成 label.grid(row = 0, column = 0, sticky = "wens") #ラベル1を配置 textBox = tk.Entry(root) #テキストボックスWidget1を生成 textBox.grid(row = 0, column = 1, sticky = "wens", padx = 10, pady = 10) #テキストボックス1を配置 button = tk.Button(root, text="Button") #ボタンWidgetを生成 button.grid(row = 1, column = 0, columnspan = 2, sticky = "wens", padx = 10, pady = 10) #ボタンを配置 root.rowconfigure(0, weight=1) #1行目の引き伸ばし設定 root.rowconfigure(1, weight=1) #2行目の引き伸ばし設定 root.columnconfigure(0, weight=1) #1列目の引き伸ばし設定 root.columnconfigure(1, weight=1) #2列目の引き伸ばし設定 root.mainloop() #イベントループ
■実行結果
■解説
6,7行目でラベルの生成と配置、9,10行目でテキストボックスの生成と配置、12,13行目でボタンの生成と配置をしています。
GUI を引き伸ばすと、それぞれの Widget もあわせて引き伸ばされるよう、gridのオプションを sticky = “wens” としています。
※上記だけでは実現できず、15~18行目の行と列の引き伸ばし設定が必要でした。
まとめ
最後までご覧いただきありがとうございました!
tkinter の Widget の概要と、配置方法の下記3パターンをまとめました。
- place
- pack
- grid
個人的には、gridを使いこなせば、EXCELで設計できるようなGUIを作れると思います。
外枠にあわせて Widget を引き伸ばせたりと、tkinter でもある程度、実用的なGUIが作れると思いました。
質問やお気づきの点がございましたら、twitterなどで問い合わせいただければと思います><