ここのところ,pythonの標準GUIライブラリ「Tkinter」を利用したアプリ開発の練習をしています。今回は簡単な例として,入力された身長・体重の値からBMI指数を計算するアプリを作成してみました。このページでは,この開発事例について紹介します。
読者の皆さんの開発の参考になれば幸いです。
(紹介しているコードは github にて公開しています)
Tkinterとは
「Tkinter」は,pythonに標準で付属するGUI1ライブラリです。Tcl/Tk の Tk 部分をpythonで利用できるようにしたもので,これによりpythonからGUI画面を持ったアプリケーション開発が可能になります2。
開発環境
- python: 3.7.9
必要なのはpythonのみです。pythonベースのアプリ開発における「Tkinter」の有意点の一つはここにあり,簡単に開発を始めることができます。
ソースコード
早速ですが,開発したBMI指数計算アプリのソースコードです。Appクラスを作成し,メソッドで利用して処理を実現する,オブジェクト指向型プログラミングで開発を行っています。手続き型プログラミングでも処理を記述することも可能ですが,機能追加など開発場面を意識するのであれば,オブジェクト指向に慣れておくに越したことはないと思います。
各メソッドの詳細は後述しますが,「Tkinter」のウィジェット3呼び出しやBMI計算処理は個別のメソッドで記述しています。アプリの起動は,生成したAppインスタンスからlaunch()メソッドを実行することで行っています。
以下のコードをコピペ・実行するだけで,アプリが起動します。
# -*- coding: utf-8 -*-
"""
@author: data-anal-ojisan
"""
import tkinter as tk
class App:
def __init__(self):
self.root = tk.Tk() # ウィンドウの呼び出し
self.root.title('BMI Calculator') # ウィンドウタイトル設定
self.root.geometry('250x150') # ウィンドウサイズ設定
# 身長・体重・BMI指数に関連付けるtk.DoubleVar()をまとめたdictionary
self.values = {'height': tk.DoubleVar(value=170.0),
'weight': tk.DoubleVar(value=60.0),
'bmi': tk.DoubleVar()}
def launch(self):
"""
アプリ起動メソッド
"""
self.call_input_fields() # 身長・体重の入力フィールドウィジェットを呼び出す
self.call_calculate_button() # BMI計算を実行するボタンwidgetを呼び出す
self.call_result_field() # 計算結果を表示するラベルウィジェットを呼び出す
self.root.mainloop() # アプリの起動状態を維持する
def call_input_fields(self):
"""
身長・体重の入力フィールドウィジェットを呼び出すメソッド
"""
# ウィジェット配置のためのFrameを作成
frame = tk.Frame(self.root, relief="ridge", bd=1)
frame.pack(fill=tk.BOTH, padx=5, pady=5)
# 身長の入力フィールドを作成
tk.Label(frame, text='身長 (cm)', width=10).grid(row=0, column=0, padx=5, pady=5)
tk.Entry(frame, textvariable=self.values['height'], width=15).grid(row=0, column=1, padx=5, pady=5)
# 体重の入力フィールドを作成
tk.Label(frame, text='体重 (kg)', width=10).grid(row=1, column=0, padx=5, pady=5)
tk.Entry(frame, textvariable=self.values['weight'], width=15).grid(row=1, column=1, padx=5, pady=5)
def call_calculate_button(self):
"""
BMI計算実行ボタンを呼び出すメソッド
"""
# ボタンを作成
tk.Button(self.root,
text='計算',
command=self.calculate).pack(fill=tk.X, padx=5, pady=5)
def calculate(self):
"""
BMI指数を計算するメソッド
"""
# BMI指数を計算{体重(kg) / 身長(m)*身長(m)}
bmi = self.values['weight'].get() / (self.values['height'].get() / 100)**2
# 計算結果をtk.DoubleVar()に反映
self.values['bmi'].set(bmi)
def call_result_field(self):
"""
BMI指数計算結果を表示するラベルを呼び出すメソッド
"""
# ウィジェット配置のためのFrameを作成
frame = tk.Frame(self.root, bg='white')
frame.pack(fill=tk.BOTH, padx=5, pady=5)
# ラベルを作成
tk.Label(frame, text='あなたのBMI指数', width=15, bg='white').pack(side=tk.LEFT)
tk.Label(frame, textvariable=self.values['bmi'], bg='white').pack(side=tk.LEFT)
if __name__ == '__main__':
app = App()
app.launch()
__init__
Appクラスのインスタンスを生成した際4に実行されるコンストラクタです。アプリのウィンドウ設定や,身長・体重・BMI指数の値に関連付けるtk.DoubleVar()をdictionary形式で宣言しています。
def __init__(self):
self.root = tk.Tk() # ウィンドウの呼び出し
self.root.title('BMI Calculator') # ウィンドウタイトル設定
self.root.geometry('250x150') # ウィンドウサイズ設定
# 身長・体重・BMI指数に関連付けるtk.DoubleVar()をまとめたdictionary
self.values = {'height': tk.DoubleVar(value=170.0),
'weight': tk.DoubleVar(value=60.0),
'bmi': tk.DoubleVar()}
launch()
Appクラスのメソッドを実行し,ウィジェット呼び出しやアプリの起動状態を維持するためのメソッドです。各メソッドで実行する処理の概要は,コメントの通りです。
def launch(self):
"""
アプリ起動メソッド
"""
self.call_input_fields() # 身長・体重の入力フィールドウィジェットを呼び出す
self.call_calculate_button() # BMI計算を実行するボタンwidgetを呼び出す
self.call_result_field() # 計算結果を表示するラベルウィジェットを呼び出す
self.root.mainloop() # アプリの起動状態を維持する
call_input_fields()
身長・体重の入力フィールドを呼び出すメソッドです。tk.Frame() を呼び出すことでウィジェットの配置領域を作成し,その内部に入力フィールドとして tk.Label() や tk.Entry() を呼び出しています。
ここでは,入力値を受け取る tk.Entry() の textvariable オプションに インスタンス変数 values の tk.DoubleVar() をバインドしています。これにより,tk.DoubleVar() を参照することで,入力値を受け取れるようになります5。

def call_input_fields(self):
"""
身長・体重の入力フィールドウィジェットを呼び出すメソッド
"""
# ウィジェット配置のためのFrameを作成
frame = tk.Frame(self.root, relief="ridge", bd=1)
frame.pack(fill=tk.BOTH, padx=5, pady=5)
# 身長の入力フィールドを作成
tk.Label(frame, text='身長 (cm)', width=10).grid(row=0, column=0, padx=5, pady=5)
tk.Entry(frame, textvariable=self.values['height'], width=15).grid(row=0, column=1, padx=5, pady=5)
# 体重の入力フィールドを作成
tk.Label(frame, text='体重 (kg)', width=10).grid(row=1, column=0, padx=5, pady=5)
tk.Entry(frame, textvariable=self.values['weight'], width=15).grid(row=1, column=1, padx=5, pady=5)
call_calculate_button()
後述の calculate メソッドを実行するボタンを呼び出すメソッドです。

このメソッドでは単純に,tk.Button() でボタンwidgetを呼び出し,command オプションにBMI指数計算を実行するメソッドを与えているだけです。
def call_calculate_button(self):
"""
BMI計算実行ボタンを呼び出すメソッド
"""
# ボタンを作成
tk.Button(self.root,
text='計算',
command=self.calculate).pack(fill=tk.X, padx=5, pady=5)
calculate()
call_calculate_button() のボタンに対応付けられた,BMI指数を計算するためのメソッドです。
BMI指数の計算式{体重(kg) / 身長(m)*身長(m)}に従い,入力フィールドの値を代入してBMI指数を求めています。get() を利用することで,変数 values の tk.DoubleVar(),つまり入力フィールドから値を取り出しています。
BMI指数の計算結果は,変数 values のBMI指数に対応する tk.DoubleVar() に与えます。
def calculate(self):
"""
BMI指数を計算するメソッド
"""
# BMI指数を計算{体重(kg) / 身長(m)*身長(m)}
bmi = self.values['weight'].get() / (self.values['height'].get() / 100)**2
# 計算結果をtk.DoubleVar()に反映
self.values['bmi'].set(bmi)
call_result_field()
BMI指数の計算結果を表示するラベルを呼び出すメソッドです。

2つ目のラベル(tk.Label())の textvariableに対し,BMI指数に対応する tk.DoubleVar() を関連付けています。これにより,calculate() の実行により求められたBMI指数がラベルに反映される仕組みです。
def call_result_field(self):
"""
BMI指数計算結果を表示するラベルを呼び出すメソッド
"""
# ウィジェット配置のためのFrameを作成
frame = tk.Frame(self.root, bg='white')
frame.pack(fill=tk.BOTH, padx=5, pady=5)
# ラベルを作成
tk.Label(frame, text='あなたのBMI指数', width=15, bg='white').pack(side=tk.LEFT)
tk.Label(frame, textvariable=self.values['bmi'], bg='white').pack(side=tk.LEFT)
アプリ起動
App クラスのインスタンスを生成し,launch() メソッドを実行します。launch() メソッドに記述された,ウィジェット呼び出し等のコードが処理されることでアプリが起動します。

if __name__ == '__main__':
app = App()
app.launch()
まとめ
BMI指数計算アプリの説明は以上です。基本的には,ラベルやボタン等のウィジェットを呼び出し,それらに数値や処理を対応付けるだけで,アプリ開発ができます。表示されるBMI指数の桁数調整や,ウィジェットの配置位置など,ビジュアル調整は必要ですが,要求される最低限の機能は満たしていると思います。
また,pythonには機械学習やニューラルネットワークに関連するライブラリが豊富に存在するため,これらの処理を搭載したアプリ開発も可能です(作成例はこちら)。
このページが,皆さんのアプリ開発の参考になれば幸いです。
- グラフィカルユーザーインタフェース
- 出典: wikipedia
- GUIの部品
- app = App()
- tk.DoubleVar() を使用せず,tk.Entry().get() メソッドを使用することで tk.Entry() に入力されている値を取り出すことも可能です。
コメント