「日経ソフトウェア2022年9月号 特集2 Python デスクトップアプリを作ろう」を実行してみました。
サンプルプログラム
サンプルプログラムは日経ソフトウェアのWebからダウンロードできます。
以下URLから「本誌バックナンバーを見る」→「2022年9月号」→「「特集2 Pythonでデスクトップアプリを作ろう 前編」(t22209.zip))」
nkbp.jp
PART2 「BMI計算機」アプリを作ろう
BMIは体重÷(身長x身長)で求める肥満度を表す計算式です。
BMIの値が18.5未満であれば低体重、18.5以上25.0未満であれば普通体重、25.0以上30.0未満なら肥満度1と判定します。
前回のlabel部分をButtonに変更することでボタンが実装できます。
前回の記述:label = tk.Label(root,text='ここをクリック',foreground='red')
今回: btn = tk.Button(root, text='表示', command=click)
click関数は前回同様、左クリックされたらtxtをゲットしてメッセージボックスで表示します。
root = tk.Tk()
root.title('ボタンテスト')
root.geometry('300x150')
txt = tk.Entry(width=20)
txt.pack(pady=50)
# ハンドラ関数
def click():
messagebox.showinfo('メッセージ', txt.get())
btn = tk.Button(root, text='表示', command=click)
btn.pack()
root.mainloop()
実行結果
テキストボックスに文字を記入してボタンを押すと、メッセージボックスが起動し、テキストの内容を表示します。
glid関数でウィジェットを格子状に配置する
grid関数を使用するとウィジェットを格子状に配置できます。
Labelウィジェットを8個生成し、grid関数を8回実行します。
root = tk.Tk()
root.title('Grid Test')
root.geometry('400x200')
labels = [tk.Label(root, text='NO_'+str(num),
relief=tk.SOLID)
# grid関数で配置
labels[num].grid()
root.mainloop()
実行結果
8個の格子状のLabel表示ができました。
gridに引数を与えることで所望の場所に配置できます。
columnは列、rowは行を表します。
最初のラベルは0列0行、次のラベルは1列0行・・と表示されます。
root = tk.Tk()
root.title('Grid Test')
root.geometry('400x200')
labels = [tk.Label(root, text='NO_'+str(num),
relief=tk.SOLID)
# grid関数で配置
labels[0].grid(column=0, row=0)
labels[1].grid(column=1, row=0)
labels[2].grid(column=2, row=0)
labels[3].grid(column=3, row=0)
labels[4].grid(column=0, row=1)
labels[5].grid(column=1, row=1)
labels[6].grid(column=2, row=1)
labels[7].grid(column=3, row=1)
root.mainloop()
実行結果
"columnconfigure"と"rowconfigure"関数を使用すると行と行の間隔、列と列の間隔を調整できます。
root = tk.Tk()
root.title('Grid Test')
root.geometry('400x200')
labels = [tk.Label(root, text='NO_'+str(num),
relief=tk.SOLID)
# 各列の割合を指定
root.columnconfigure(0, weight=1)
root.columnconfigure(1, weight=1)
root.columnconfigure(2, weight=1)
root.columnconfigure(3, weight=1)
# 各行の割合を指定
root.rowconfigure(0, weight=1)
root.rowconfigure(1, weight=1)
# grid関数で配置
labels[0].grid(column=0, row=0)
labels[1].grid(column=1, row=0)
labels[2].grid(column=2, row=0)
labels[3].grid(column=3, row=0)
labels[4].grid(column=0, row=1)
labels[5].grid(column=1, row=1)
labels[6].grid(column=2, row=1)
labels[7].grid(column=3, row=1)
root.mainloop()
実行結果
引数のweightを1に設定しているため、均等に表示されています。
適当に値をかえて実行してみると
# 各列の割合を指定
root.columnconfigure(0, weight=1)
root.columnconfigure(1, weight=4)
root.columnconfigure(2, weight=4)
root.columnconfigure(3, weight=1)
# 各行の割合を指定
root.rowconfigure(0, weight=5)
root.rowconfigure(1, weight=1)
実行結果
columnconfigureでweightを4に変えてみました。4つの列のうちNO_1とNO_2の領域の割合が4割づつとなっています。
行のほうは、rowconfigureでweightを5対1に設定してみた結果です。
grid関数の引数にstickyをさらに領域内のどの辺に指定するかを設定できます。
NSEWで設定します。Nは上方向、Sは下方向、Eは右方向、Wは左方向に配置します。
NE、SWなどを指定すると左上方向、右下方向に配置されます。
NSEWすべてを指定すると領域全体に配置されます。
root = tk.Tk()
root.title('Grid Test')
root.geometry('400x200')
labels = [tk.Label(root, text='NO_'+str(num),
relief=tk.SOLID)
root.columnconfigure(0, weight=1)
root.columnconfigure(1, weight=1)
root.columnconfigure(2, weight=1)
root.columnconfigure(3, weight=1)
root.rowconfigure(0, weight=1)
root.rowconfigure(1, weight=1)
# grid関数で配置
labels[0].grid(column=0, row=0, sticky=tk.N)
labels[1].grid(column=1, row=0, sticky=tk.S)
labels[2].grid(column=2, row=0, sticky=tk.E)
labels[3].grid(column=3, row=0, sticky=tk.W)
labels[4].grid(column=0, row=1, sticky=tk.NS)
labels[5].grid(column=1, row=1, sticky=tk.SE)
labels[6].grid(column=2, row=1, sticky=tk.EW)
labels[7].grid(column=3, row=1, sticky=tk.NSEW)
root.mainloop()
実行結果
NO_0、NO_1、NO_2、NO_3がまず同じ行にweight=1なので均等に配置されます。
その後。stickyで「上」「下」「右」「左」と指定しているので、各自の領域の中でそれぞれ指定された部分に格子状に配置されています。
NO_4、NO_5、NO_6、NO_7は「上下」「右下」、「左右」、「上下左右」に配置されています。
rowやcolumnの複数の領域に一つのウィジェットを割り当てる場合は、rowspanやcolumnpanを使用します。
NO_0はrowspan=2で2行、NO_1はcolumnspan=2で2列、NO_3はcolumnspan=3で3列分の領域をとります。
root = tk.Tk()
root.title('Grid Test')
root.geometry('400x200')
labels = [tk.Label(root, text='NO_'+str(num),
relief=tk.SOLID)
root.columnconfigure(0, weight=1)
root.columnconfigure(1, weight=1)
root.columnconfigure(2, weight=1)
root.columnconfigure(3, weight=1)
root.rowconfigure(0, weight=1)
root.rowconfigure(1, weight=1)
# grid関数で配置
labels[0].grid(column=0, row=0, rowspan=2)
labels[1].grid(column=1, row=0, columnspan=2)
labels[2].grid(column=3, row=0)
labels[3].grid(column=1, row=1, columnspan=3)
root.mainloop()
実行結果
最後に、BMI計算機の各ウィジェットの配置を考慮したプログラムを実行すると、
以下のアプリが起動します。
def calc(weight, height):
return weight / (height**2)
# 肥満度判定関数
result = '低体重'
result = '普通体重'
result = '肥満度1'
result = '肥満度2'
result = '肥満度3'
else:
result = '肥満度4'
return result
root = tk.Tk()
root.title('肥満度チェック')
root.geometry('250x150')
label_1 = tk.Label(root, text='体重')
label_2 = tk.Label(root, text='kg')
label_3 = tk.Label(root, text='身長')
label_4 = tk.Label(root, text='cm')
label_5 = tk.Label(root, text='体重と身長を入力してください。')
weight = tk.Entry(width=5)
height = tk.Entry(width=5)
# Buttonのハンドラ関数
def judgement():
w = float(weight.get())
h = float(height.get()) / 100
s = check(calc(w, h))
label_5['text'] = '肥満度:' + str(s)
button = tk.Button(root, text='BMI判定', command=judgement)
root.columnconfigure(0, weight=1)
root.columnconfigure(1, weight=1)
root.columnconfigure(2, weight=1)
root.rowconfigure(0, weight=1)
root.rowconfigure(1, weight=1)
root.rowconfigure(2, weight=1)
root.rowconfigure(3, weight=1)
label_1.grid(column=0, row=0, sticky=tk.E)
weight.grid(column=1, row=0)
label_2.grid(column=2, row=0, sticky=tk.W)
label_3.grid(column=0, row=1, sticky=tk.E)
height.grid(column=1, row=1)
label_4.grid(column=2, row=1, sticky=tk.W)
button.grid(column=0, row=2, columnspan=3)
label_5.grid(column=0, row=3, columnspan=3)
root.mainloop()
身長と体重を入力し、ボタンをクリックすると、肥満度が表示されます。