Pythonのtkinterで簡単なGUI電卓アプリを作る方法【初心者向け】
はじめに
Pythonでは、tkinterライブラリを使ってGUIコンポーネントを作成し、より使いやすいユーザーインターフェースを構築することができます。
この記事では、tkinterとPillow(PIL)を組み合わせて、アイコン付きのシンプルなGUI電卓アプリケーションを作成する方法を、初心者向けに丁寧に解説していきます。
事前準備
開発を始める前に、いくつか準備しておくべきことがあります。
まず、ローカルシステムから画像ファイルを読み込むために使用するPythonの画像処理ライブラリをインストールしましょう。PIL(Pillow)をインストールするには、ターミナルを起動して以下のコマンドを実行してください。
pip install Pillow
パッケージのインストールが完了したら、次に電卓に必要なアイコン画像をダウンロードします。
Google画像検索などで必要なアイコンを各自で用意しても構いませんが、本プロジェクトで使用したものと同じアイコンセットが必要な場合は、以下のリンクからダウンロードできます。
https://www.dropbox.com/sh/0zqd6zd9b8asmor/AAC3d2iOvMRl8INkbCuMUo_ya?dl=0
重要: ダウンロードしたすべてのアイコンは、「asset」という名前のフォルダに保存してください。フォルダ名や配置場所が異なると、後述のコードが正しく動作しません。
続いて、必要なモジュールをインポートします。
from tkinter import * from PIL import Image # pip install Pillow from PIL import ImageTk
以上で準備は完了です。ここまでできれば、開発を始める環境がすべて整っています。
関数の作成
まず最初に、GUIコンポーネントから呼び出される関数を作成します。
主な関数は3つあります。数字や記号のボタンが押されたときに呼ばれる関数、イコール(=)ボタンが押されたときに呼ばれる関数、そしてクリア(C)ボタンが押されたときに呼ばれる関数です。
まず、これらの関数で共有するグローバル変数を初期化しておきましょう。
txt = "" res = False ans = 0
- txt:現在入力中の計算式を保持する文字列
- res:直前に計算結果を表示したかどうかを示すフラグ
- ans:直前の計算結果を保持する値
数字キーが押されたときの関数
def press(num): global txt, ans, res if (res==True): txt = ans res = False txt = txt + str(num) equation.set(txt)
この関数では、押された数字や記号を受け取って現在の式(txt)に連結し、画面表示を更新しています。resがTrueの場合(直前に計算を実行した直後)は、新しい入力を始めるために式を前回の計算結果でリセットする仕組みです。
イコールボタンが押されたときの関数
def equal():
try:
global txt, ans, res
ans = str(eval(txt))
equation.set(ans)
res = True
except:
equation.set("ERROR : Invalid Equation")
txt=""イコールボタンが押されると、eval()関数によって入力された式が評価され、その結果が画面に表示されます。無効な式が入力された場合には、try-except構文によってエラーが捕捉され、「ERROR : Invalid Equation」というメッセージが表示されます。
クリアボタンが押されたときの関数
def clear():
global txt, ans, res
txt = ""
equation.set("")
res = Falseクリアボタンが押されると、入力中の式とフラグがすべて初期化され、電卓がまっさらな状態に戻ります。
メイン処理とウィンドウの作成
関数の定義が完了したら、メイン処理を開始してGUIコンポーネントの構築に取り掛かりましょう。
if __name__ == "__main__":
window = Tk()
window.configure(background="black")
window.title("Calculator")
window.iconbitmap("assets\Calculator\Logo.ico")
window.geometry("343x417")
window.resizable(0,0)上記のコードにより、電卓アプリの基本となるウィンドウ構造が整います。背景色、タイトル、アイコン、ウィンドウサイズ(343×417ピクセル)、リサイズ禁止の設定を行っています。
注意: エラーを避けるため、必ず以下のようなファイル構成に従ってください。ロゴアイコンは、assetsフォルダの中にあるCalculatorフォルダ内に保存します。
+---Working Directory +---Calculator.py +---assets +---Calculator +---All the icons.
表示フィールドの作成
次に、入力した数字や計算結果を表示するためのテキストフィールドをデザインしましょう。
equation = StringVar()
txt_field = Entry(relief=RIDGE,textvariable=equation,bd=10,font=("Aerial",20),bg="powder blue")
txt_field.grid(columnspan=4,ipady=10,ipadx=10,sticky="nsew")StringVar()はtkinterの特殊な変数オブジェクトで、Entryウィジェットの内容と自動的に同期されます。これにより、equation.set()を呼び出すだけで画面表示を更新できるのです。
ボタンの追加
続いて、アイコン画像をGUIウィンドウに一つずつ追加していく作業を行います。以下は「1」のボタンを追加する場合の一例です。他のボタンもまったく同じ手順で追加できるので、このパターンを参考にするか、記事末尾の完全なコードからコピーしてください。
width=80
height=80
img1 = Image.open("assets/Calculator/one.PNG")
img1 = img1.resize((width,height))
oneImage = ImageTk.PhotoImage(img1)
button1 = Button(window, image=oneImage,bg="white",command = lambda:press(1),height=height,width=width)
button1.grid(row=2,column=0,sticky="nsew")ここでの流れは以下の通りです。
- Pillowの
Image.open()でアイコン画像を読み込む resize()で80×80ピクセルにリサイズするImageTk.PhotoImage()でtkinterで使える画像オブジェクトに変換するButtonウィジェットを作成し、command引数にlambda式でクリック時の動作を指定するgrid()で行・列の位置を指定して配置する
上記と同様の手順で、button2、button3と続けていき、すべての数字(0〜9)と演算記号(+、−、×、÷)、イコール、クリアのボタンを配置してください。
これで完成です。プログラムを実行すると、アイコンを使ったシンプルで見栄えの良い電卓が表示されるはずです。
完全なソースコード
途中でうまくいかない場合は、以下の完全なコードを参考にしてください。
from tkinter import *
from PIL import Image
from PIL import ImageTk
txt = ""
res = False
ans = 0
def press(num):
global txt, ans, res
if (res==True):
txt = ans
res = False
txt = txt + str(num)
equation.set(txt)
def equal():
try:
global txt, ans, res
ans = str(eval(txt))
equation.set(ans)
res = True
except:
equation.set("ERROR : Invalid Equation")
txt=""
def clear():
global txt, ans, res
txt = ""
equation.set("")
res = False
if __name__ == "__main__":
window = Tk()
window.configure(background="black")
window.title("Calculator")
window.iconbitmap("assets\Calculator\Logo.ico")
window.geometry("343x417")
window.resizable(0,0)
equation = StringVar()
txt_field = Entry(relief=RIDGE,textvariable=equation,bd=10,font=("Aerial",20),bg="powder blue")
txt_field.grid(columnspan=4,ipady=10,ipadx=10,sticky="nsew")
width=80
height=80
img1 = Image.open("assets/Calculator/one.PNG")
img1 = img1.resize((width,height))
oneImage = ImageTk.PhotoImage(img1)
button1 = Button(window, image=oneImage,bg="white",command = lambda:press(1),height=height,width=width)
button1.grid(row=2,column=0,sticky="nsew")
img2 = Image.open("assets/Calculator/two.PNG")
img2 = img2.resize((width,height))
twoImage = ImageTk.PhotoImage(img2)
button2 = Button(window, image=twoImage,bg="white",command = lambda:press(2),height=height,width=width)
button2.grid(row=2,column=1,sticky="nsew")
img3 = Image.open("assets/Calculator/three.PNG")
img3 = img3.resize((width,height))
threeImage = ImageTk.PhotoImage(img3)
button3 = Button(window, image=threeImage,bg="white",command = lambda:press(3),height=height,width=width)
button3.grid(row=2,column=2,sticky="nsew")
img4 = Image.open("assets/Calculator/four.PNG")
img4 = img4.resize((width,height))
fourImage = ImageTk.PhotoImage(img4)
button4 = Button(window, image=fourImage,bg="white",command = lambda:press(4),height=height,width=width)
button4.grid(row=3,column=0,sticky="nsew")
img5 = Image.open("assets/Calculator/five.PNG")
img5 = img5.resize((width,height))
fiveImage = ImageTk.PhotoImage(img5)
button5 = Button(window, image=fiveImage,bg="white",command = lambda:press(5),height=height,width=width)
button5.grid(row=3,column=1,sticky="nsew")
img6 = Image.open("assets/Calculator/six.PNG")
img6 = img6.resize((width,height))
sixImage = ImageTk.PhotoImage(img6)
button6 = Button(window, image=sixImage,bg="white",command = lambda:press(6),height=height,width=width)
button6.grid(row=3,column=2,sticky="nsew")
img7 = Image.open("assets/Calculator/seven.PNG")
img7 = img7.resize((width,height))
sevenImage = ImageTk.PhotoImage(img7)
button7 = Button(window, image=sevenImage,bg="white",command = lambda:press(7),height=height,width=width)
button7.grid(row=4,column=0,sticky="nsew")
img8 = Image.open("assets/Calculator/eight.PNG")
img8 = img8.resize((width,height))
eightImage = ImageTk.PhotoImage(img8)
button8 = Button(window, image=eightImage,bg="white",command = lambda:press(8),height=height,width=width)
button8.grid(row=4,column=1,sticky="nsew")
img9 = Image.open("assets/Calculator/nine.PNG")
img9 = img9.resize((width,height))
nineImage = ImageTk.PhotoImage(img9)
button9 = Button(window, image=nineImage,bg="white",command = lambda:press(9),height=height,width=width)
button9.grid(row=4,column=2,sticky="nsew")
img0 = Image.open("assets/Calculator/zero.PNG")
img0 = img0.resize((width,height))
zeroImage = ImageTk.PhotoImage(img0)
button0 = Button(window, image=zeroImage,bg="white",command = lambda:press(0),height=height,width=width)
button0.grid(row=5,column=1,sticky="nsew")
imgx = Image.open("assets/Calculator/multiply.PNG")
imgx = imgx.resize((width,height))
multiplyImage = ImageTk.PhotoImage(imgx)
buttonx = Button(window, image=multiplyImage,bg="white",command = lambda:press("*"),height=height,width=width)
buttonx.grid(row=2,column=3,sticky="nsew")
imgadd = Image.open("assets/Calculator/add.PNG")
imgadd = imgadd.resize((width,height))
addImage = ImageTk.PhotoImage(imgadd)
buttonadd = Button(window, image=addImage,bg="white",command = lambda:press("+"),height=height,width=width)
buttonadd.grid(row=3,column=3,sticky="nsew")
imgdiv = Image.open("assets/Calculator/divide.PNG")
imgdiv = imgdiv.resize((width,height))
divImage = ImageTk.PhotoImage(imgdiv)
buttondiv = Button(window, image=divImage,bg="white",command = lambda:press("/"),height=height,width=width)
buttondiv.grid(row=5,column=3,sticky="nsew")
imgsub = Image.open("assets/Calculator/subtract.PNG")
imgsub = imgsub.resize((width,height))
subImage = ImageTk.PhotoImage(imgsub)
buttonsub = Button(window, image=subImage,bg="white",command = lambda:press("- "),height=height,width=width)
buttonsub.grid(row=4,column=3,sticky="nsew")
imgeq = Image.open("assets/Calculator/equal.PNG")
imgeq = imgeq.resize((width,height))
eqImage = ImageTk.PhotoImage(imgeq)
buttoneq = Button(window, image=eqImage,bg="white",command = equal,height=height,width=width)
buttoneq.grid(row=5,column=2,sticky="nsew")
imgclear = Image.open("assets/Calculator/clear.PNG")
imgclear = imgclear.resize((width,height))
clearImage = ImageTk.PhotoImage(imgclear)
buttonclear = Button(window, image=clearImage,bg="white",command = clear,height=height,width=width)
buttonclear.grid(row=5,column=0,sticky="nsew")
window.mainloop()上記のプログラムでコードの整形に問題がある場合は、GitHubのこちらのページからも取得できます。
実行結果

-
Python Tkinterで作る簡単な登録フォーム入門
Tkinterは、GUI(グラフィカルユーザーインターフェース)を開発するためのPython標準ライブラリです。Tkinterを使うことで、ウィンドウをはじめとするさまざまなUI(ユーザーインターフェース)要素を持つデスクトップアプリケーションを作成できます。推奨されているPython 3.xを使用している場合、TkinterはPythonに標準搭載されているパッケージなので、追加のインストールは一切不要です。この記事では、まずTkinterの基本的なGUIアプリケーションの作り方を解説し、その後、実際の登録フォームやローン金利計算ツールといった実用的な例まで段階的に見ていきます。シンプルなG
-
【Python】Tkinterで作るカラーゲーム – 30秒で文字の色を当てるGUIゲーム開発
GUIアプリケーションの開発において、Pythonの標準ライブラリ「Tkinter」は非常に人気が高く、初心者でも扱いやすいツールです。追加のインストール作業なしに使えるため、Tkinterを活用すればシンプルなGUIゲームでも手軽に開発できます。 この記事では、Tkinterを使った「カラーゲーム」の作り方を紹介します。このゲームでは、画面に表示される単語の文字色をプレイヤーが入力し、正解するたびにスコアが1点ずつ加算されます。制限時間は30秒で、使用される色は赤(Red)、青(Blue)、緑(Green)、ピンク(Pink)、黒(Black)、黄(Yellow)、オレンジ(Orange)、