ひとりでのアプリ開発 - fineの備忘録 -

ひとりでアプリ開発をするなかで起こったことや学んだことを書き溜めていきます

Python - 電卓アプリを作ってみた

初めに

 PythonTkinter を使い、電卓アプリを作ってみました。本記事は、ウィジェット変数や sticky などその際に学んだことをまとめます。

完成イメージ


コード全文

import tkinter as tk

def calculate():
    try:
        result = eval(entry.get())
        entry.delete(0, tk.END)  # 結果を表示する前にエントリーボックスをクリア
        entry.insert(tk.END, str(result))  # 結果を表示
    except Exception as e:
        entry.delete(0, tk.END)  # エラーがあればエントリーボックスをクリア
        entry.insert(tk.END, "エラー")

def clear():
    entry.delete(0, tk.END)

# メインウィンドウの作成
root = tk.Tk()
root.title("計算機")

# エントリーボックス
entry = tk.Entry(root, width=20)
entry.grid(row=0, column=0, columnspan=4, sticky="nsew")

# ボタンのレイアウト
buttons = [
    '7', '8', '9', '/',
    '4', '5', '6', '*',
    '1', '2', '3', '-',
    '0', 'C', '=', '+'
]

# ボタンの作成と配置
row_val = 1
col_val = 0
for button in buttons:
    action = lambda x=button: entry.insert(tk.END, x)
    

    # イコールボタンに関数の割り当て
    if col_val == 2 and row_val == 4:
        tk.Button(root, text='=', width=5, height=2, command=calculate).grid(row=row_val, column=col_val, sticky="nsew")
    elif col_val == 1 and row_val == 4:
        tk.Button(root, text='C', width=5, height=2, command=clear).grid(row=row_val, column=col_val, sticky="nsew")
    else:
        tk.Button(root, text=button, width=5, height=2, command=action).grid(row=row_val, column=col_val, sticky="nsew")

    col_val += 1
    if col_val > 3:
        col_val = 0
        row_val += 1

# 結果表示用のラベル
result = tk.StringVar()
result.set("")
result_label = tk.Label(root, textvariable=result)
result_label.grid(row=row_val, column=0, columnspan=4, sticky="nsew")

# グリッドの設定
for i in range(5):
    root.grid_rowconfigure(i, weight=1)
    root.grid_columnconfigure(i, weight=1)

root.mainloop()

コード解説

Tkinter のインポート
import tkinter as tk

 電卓をウィンドウに表示させたいので、Tkinter をインポートします。

ウィンドウ、ウィジェットの作成、配置
# メインウィンドウの作成
root = tk.Tk()
root.title("計算機")

# エントリーボックス
entry = tk.Entry(root, width=20)
entry.grid(row=0, column=0, columnspan=4, sticky="nsew")

# ボタンのレイアウト
buttons = [
    '7', '8', '9', '/',
    '4', '5', '6', '*',
    '1', '2', '3', '-',
    '0', 'C', '=', '+'
]

# ボタンの作成と配置
row_val = 1
col_val = 0
for button in buttons:
    action = lambda x=button: entry.insert(tk.END, x)
    
    if col_val == 2 and row_val == 4:    # イコールボタンに関数の割り当て
        tk.Button(root, text='=', width=5, height=2, command=calculate).grid(row=row_val, column=col_val, sticky="nsew")
    elif col_val == 1 and row_val == 4:    # クリアボタンに関数の割り当て
        tk.Button(root, text='C', width=5, height=2, command=clear).grid(row=row_val, column=col_val, sticky="nsew")
    else:
        tk.Button(root, text=button, width=5, height=2, command=action).grid(row=row_val, column=col_val, sticky="nsew")

    col_val += 1
    if col_val > 3:
        col_val = 0
        row_val += 1

# 結果表示用のラベル
result = tk.StringVar()
result.set("")
result_label = tk.Label(root, textvariable=result)
result_label.grid(row=row_val, column=0, columnspan=4, sticky="nsew")

 いくつかポイントとなる部分をピックアップして解説します。

〇関数の割り当て
 数字や+, -, *, / などの演算子は command=actionの部分で関数を割り当てています。lambda を使い、無名関数を定義して、action に代入しています。

entry.insert(文字の位置、セットしたい文字列) 
tk.End  # 文字列の最後

 = と C には、それぞれ計算結果を出力するための calculate 関数とエントリーをクリアするための clear 関数を去り当てます。これらの関数の中身は後述します。

〇grid に配置
 for button in buttons: を使い、繰り返し処理を行い、すべてのボタンを配置していきます。buttons の要素が 4 × 4 =16 個あるので、16 回繰り返されます。

tk.Button(root, text=button, width=5, height=2, command=action).grid(row=row_val, column=col_val, sticky="nsew")

 .grid(row=行, column=列, sticky="nsew") で何行何列に配置するか指定します。sticky はウィジェットを寄せる方向を指定します。今回は nsew(北南東西すべて)なので、grid の拡大・縮小に合わせてボタンも拡大・縮小されます。

〇結果の出力、StringVar()

result = tk.StringVar()    #stringのウィジェット変数を取得
result.set("")
result_label = tk.Label(root, textvariable=result)    #Labelにウィジェット変数を割り当て

 StringVar() はウィジェット変数と呼ばれるものになります。

ウィジェット変数(制御変数)

 ウィジェット変数はウィジェットと連動する変数のことです。ウィジェットに設定することで、ウィジェットの表示を動的に変化させたり、入力を動的に取得したりすることができます。

 tkinter には次のウィジェット変数が用意されています。

  • StringVar():string
  • IntVar():int
  • DoubleVar():double
  • BooleanVar():bool

 今回の電卓の作成では、結果の出力に使用しています。

result = tk.StringVar()    #stringのウィジェット変数を取得
result.set("")
result_label = tk.Label(root, textvariable=result)    #Labelにウィジェット変数を割り当て