凡愚な僕

理系大学生の雑記と備忘録

【Tkinter】pythonで電卓を作ってみた

f:id:mizukawa815:20211003190038p:plain
pythonで電卓を作成してみたよ。

GUI構築にはTkinterを使用したよ~。


【追記:2021年10月19日】ソースコードをペッと貼り付けただけだったので解説いれました。




1. Tkinterとは

Tkinterとは、「ティーキンター」や「ティーケーインター」と呼ばれ、Window、Mac OSX、Linuxといった主要なOSにも対応しているクロスプラットフォームなGUIライブラリです。
Tkinterは、Tcl/Tkをベースにしています。
Pythonで扱うためGUIライブラリで、Python以外でも、Ruby、Perl等の言語でもTkinterのようなライブラリは存在します。

2. Tkinterの導入

TkinterはPythonの標準ライブラリであるため、既に導入済みであることが多いです。

以下を実行してポップアップが表示されれば既に導入済みです。

import tkinter
tkinter._test()

f:id:mizukawa815:20211019080023p:plain

ポップアップが表示されなければ、Tkinterが導入されていないのでインストールを進めていきましょう。

2.1. Windowsでのインストール

Windowsの場合、Pythonのインストール時にパッケージとしてTkinterをインストールします。

f:id:mizukawa815:20211019075917p:plain

『tcl/tk and IDEL』にチェックを入れて通常通りPythonをインストールしてください。

インストールが完了したら導入ができているかを確認します。

import tkinter
tkinter._test()

f:id:mizukawa815:20211019080023p:plain

無事にポップアップが表示されていれば導入は完了しています。

2.2. Ubuntu(Linux)でのインストール

以下のコマンドを打ってTkinterのインストールを行います。

sudo apt-get install python3-tk

以下を実行してインストールができているかを確認します。

python3 -m tkinter

python2 -m Tkinter

Windowsと同様にポップアップが表示されていれば導入は完了しています。

3. 実装

ほな実装していくで。
f:id:mizukawa815:20211019193446p:plain

3.1. 環境

Visual Studio Code
Python3.8
Tkinter

3.2. ソースコード


import tkinter as tk # Tkinterをインポート
fonts=("", 16) # フォントの書式とサイズを指定

class Calculator(tk.Frame):
    #ウィンドウの作成
    def __init__(self, master = None):
        tk.Frame.__init__(self, master)
        self.master.geometry()
        self.master.title('Calculator') # ウィンドウタイトルを指定
        self.entry = tk.Entry(self.master, justify='right', font=fonts) # テキストボックスを作成
        self.creat_widgets()

    #入力
    def input(self, num):
        def n():
            self.entry.insert(tk.END, num)
        return n

    #パーセント表示
    def one_hundredth(self):
        text = self.entry.get()
        self.entry.delete(0, tk.END)
        self.entry.insert(0, eval(text + '/100'))

    #計算を全てクリア
    def clear_all(self):
        self.entry.delete(0, tk.END)

    #1文字削除
    def clear_one(self):
        text = self.entry.get()
        self.entry.delete(0, tk.END)
        self.entry.insert(0, text[:-1])

    #計算結果を表示
    def equals(self):
        self.value = eval(self.entry.get().replace('÷', '/').replace('×', '*').replace('+', '+').replace('-', '-'))
        self.entry.delete(0, tk.END)
        self.entry.insert(0, self.value)

    #ディスプレイ部分を作成
    def creat_widgets(self):
        Buttons = [ 
        ['7', '8', '9'], 
        ['4', '5', '6'], 
        ['1', '2', '3'], 
        ]

        # 各ボタンを配置
        for i, ro in enumerate(Buttons):
            for j, co in enumerate(ro):
                tk.Button(self.master, font=fonts, text=co, width=10, height=2, command=self.input(co)).grid(row=i+2, column=j)

        # テキストボックスを配置
        self.entry.grid(row=0, column=0, ipady=10, columnspan=4, sticky='nsew')
        
        # 各ボタンの処理
        tk.Button(self.master, text='%', font=fonts, width=10, height=2, command=lambda: self.one_hundredth()).grid(row=1, column=0)
        tk.Button(self.master, text='CE', font=fonts, width=10, height=2, command=lambda: self.clear_all()).grid(row=1, column=1)
        tk.Button(self.master, text='←', font=fonts, width=10, height=2, command=lambda: self.clear_one()).grid(row=1, column=2)
        tk.Button(self.master, text='÷', font=fonts, width=10, height=2, command=self.input('÷')).grid(row=1, column=3)
        tk.Button(self.master, text='×', font=fonts, width=10, height=2, command=self.input('×')).grid(row=2, column=3)
        tk.Button(self.master, text='-', font=fonts, width=10, height=2, command=self.input('-')).grid(row=3, column=3)
        tk.Button(self.master, text='+', font=fonts, width=10, height=2, command=self.input('+')).grid(row=4, column=3)
        tk.Button(self.master, text='=', font=fonts, width=10, height=2, command=lambda: self.equals()).grid(row=5, column=3)
        tk.Button(self.master, text='0', font=fonts, width=21, height=2, command=self.input('0')).grid(row=5, column=0, columnspan=2)
        tk.Button(self.master, text='.', font=fonts, width=10, height=2, command=self.input('.')).grid(row=5, column=2)

# 実行
calc = Calculator(tk.Tk())
calc.mainloop()

3.3. 実行結果

f:id:mizukawa815:20211019184203p:plain

4. 解説

4.1. インポートとフォントサイズ指定

import tkinter as tk # Tkinterをインポート
fonts=("", 16) # フォントの書式とサイズを指定


tkとしてインポートします。
fonts変数には(書式, フォントサイズ)を渡します(今回はデフォルトの書式)。

4.2. ウィンドウ作成

    def __init__(self, master = None):
        tk.Frame.__init__(self, master)
        self.master.geometry("480x335+200+200") # ウィンドウのサイズ、表示位置を指定
        self.master.title('Calculator') # ウィンドウタイトル
        self.entry = tk.Entry(self.master, justify='right') # テキストボックスを作成
        self.creat_widgets()

geomery()では、ウィンドウの表示位置やサイズを指定できます。
今回は、『480x335サイズのウィンドウを(x, y) = (200, 200)の位置に表示(単位はピクセル)』と指定しています。

Entry()では、テキストボックスを生成しています。
今回作成する電卓の場合、途中式や計算結果を表示する部分になります。

4.3. テキストボックスに文字列を入力

    def input(self, num):
        def n():
            self.entry.insert(tk.END, num)
        return n

insert()を使ってテキストボックスの文字列の最後の位置(tk.END)に任意の数字を格納します。

4.4. パーセント表示

    #パーセント表示
    def one_hundredth(self):
        text = self.entry.get() # テキストボックスの値を取得
        self.entry.delete(0, tk.END) # テキストボックスの値を0文字目から最後まで削除
        self.entry.insert(0, eval(text + '/100')) # テキストボックスの値を1/100倍して入力

まず、get()でテキストボックス内の値を取得した後にdelete()でクリアします。
次に取得した値を1/100倍してテキストボックスに格納することでパーセント表示を実現しています。

4.5. テキストボックスの値を全て削除

    def clear_all(self):
        self.entry.delete(0, tk.END) # テキストボックスの値を0文字目から最後まで削除

4.6. テキストボックスの値を1文字削除

    #1文字削除
    def clear_one(self):
        text = self.entry.get()
        self.entry.delete(0, tk.END)
        self.entry.insert(0, text[:-1])

変数textにテキストボックスの値を格納し、全ての値をクリアします。
insert()で0文字目から変数textに格納した値の最後から2番目までをテキストボックスに入力することで1文字削除を実現しています。

4.7. 計算結果を表示

    #計算結果を表示
    def equals(self):
        self.value = eval(self.entry.get().replace('÷', '/').replace('×', '*').replace('+', '+').replace('-', '-')) # str型からint型へ
        self.entry.delete(0, tk.END) # テキストボックスの値を0文字目から最後まで削除
        self.entry.insert(0, self.value) # 計算結果をテキストボックスに格納

get()でテキストボックス内の値を取得します。
この時、replace(置換する文字列, 置換後の文字列)でそれぞれの四則演算子をint型に変換します。

evalメソッドで計算結果をvalueに代入し、insertメソッドで計算結果をテキストボックスに格納しています。

4.8. ディスプレイ部分の実装

    #ディスプレイ部分を作成
    def creat_widgets(self):
        Buttons = [ 
        ['7', '8', '9'], 
        ['4', '5', '6'], 
        ['1', '2', '3'], 
        ]

       # 各ボタンを配置
        for i, ro in enumerate(Buttons):
            for j, co in enumerate(ro):
                tk.Button(self.master, font=fonts, text=co, width=10, height=2, command=self.input(co)).grid(row=i+2, column=j)

        # テキストボックスを配置
        self.entry.grid(row=0, column=0, ipady=10, columnspan=4, sticky='nsew')
        
        # 各ボタンの処理
        tk.Button(self.master, text='%', font=fonts, width=10, height=2, command=lambda: self.one_hundredth()).grid(row=1, column=0)
        tk.Button(self.master, text='CE', font=fonts, width=10, height=2, command=lambda: self.clear_all()).grid(row=1, column=1)
        tk.Button(self.master, text='←', font=fonts, width=10, height=2, command=lambda: self.clear_one()).grid(row=1, column=2)
        tk.Button(self.master, text='÷', font=fonts, width=10, height=2, command=self.input('÷')).grid(row=1, column=3)
        tk.Button(self.master, text='×', font=fonts, width=10, height=2, command=self.input('×')).grid(row=2, column=3)
        tk.Button(self.master, text='-', font=fonts, width=10, height=2, command=self.input('-')).grid(row=3, column=3)
        tk.Button(self.master, text='+', font=fonts, width=10, height=2, command=self.input('+')).grid(row=4, column=3)
        tk.Button(self.master, text='=', font=fonts, width=10, height=2, command=lambda: self.equals()).grid(row=5, column=3)
        tk.Button(self.master, text='0', font=fonts, width=21, height=2, command=self.input('0')).grid(row=5, column=0, columnspan=2)
        tk.Button(self.master, text='.', font=fonts, width=10, height=2, command=self.input('.')).grid(row=5, column=2)

Button()ではfontにfontsを代入することで初めに宣言した書式とフォントサイズを指定しています。

また、commandではそれぞれのボタンが押された時の処理を指定しています。

例えば、「%ボタン」を押した場合はone_hundredth関数を呼び出してパーセント表示させています。

6. おわりに

以上で解説を終わります。

今回用いたメソッドに、使っていない引数やらがたくさんあるので興味がある方は以下を参照してください。
Python:tkinter ウィジェット共通メソッド - リファレンス メモ


簡素な電卓だけど作ってて楽しかったから時間があれば色々作ってみたいね。
f:id:mizukawa815:20211019192357p:plain

大学生がWEBサービス公開から2週間で835人のユーザを獲得したお話
【一度は読むべき】大学生におすすめの本を7冊紹介すんべ
【文系理系】大学生がプログラミングを学ぶメリット5つ