Python tkinterで計算機を作ってみる

Python学習【365日チャレンジ!】310日目のマスターU(@Udemy11)です。

Youtubeの見すぎで、昨日はホントグダグダになってしまい、計算機アプリの説明が途中で終了してしまいました。

ほんと睡眠はしっかりと取らないといけませんね。

ということで、今日もPython学習を始めましょう。

昨日の復習

昨日は、tkinterを使って、計算機アプリを作成するコードを解説している途中で睡魔が襲ってきました。

酒井さんの講座の中からサンプルコードを引用させていただき、初期化の__init__()を解説したところまでで終了しましたが、内容については、昨日の記事を御覧ください。

今日は、昨日の続きで、tkinterを使った計算機アプリのコードを解説していきます。

input()

    def input(self, action):
        self.entry.insert(tk.END, action)

input()は、計算機のボタンの操作をする関数で、引数のactionを、初期化で定義したentry(tk.Entry)のinsert()に渡しています。

ここで定義したinput関数は最後に記述するcreate_widgetsで活用します。

clear_all()

    def clear_all(self):
        self.entry.delete(0, tk.END)

ここで定義するclear_all()は、入力されたentryの値を最初(0)から最後(tk.END)まで削除(delete)するコードです。

inputと同様に、後に記述するcreate_widgetsで活用します。

clear_one()

    def clear_one(self):
        txt = self.entry.get()
        self.entry.delete(0, tk.END)
        self.entry.insert(0, txt[:-1])

clear_allは、すべての値を削除する関数でしたが、clear_oneは一つずつ値を消去する関数です。

entry.get()で、entryの値を取得してtxtに入れておき、26行目で一旦entryの値をすべて削除します。

27行目でinsert()を使って、txtから最後の1文字をのぞいた値を入れています。

equals()

    def equals(self):
        self.value = eval(self.entry.get().replace('÷', '/').replace('x', '*'))
        self.entry.delete(0, tk.END)
        self.entry.insert(0, self.value)

equalsは、計算結果を表示する関数になります。

30行目は、計算した結果をvalueに代入しているコードですが、演算子の+-は、そのまま計算できますが、÷×は演算子とは認識されないため、/*に置き換える必要があるので、replaceで置き換えて計算しています。

31行目は、すでに解説していますが、entryを削除して、32行目で値の入ったvalueを表示しています。

create_widgets()

    def create_widgets(self):
        file_menu = tk.Menu(self.menu_bar)
        file_menu.add_command(label='Exit', command=self.master.quit)
        self.menu_bar.add_cascade(label='File', menu=file_menu)

        self.entry.grid(row=0, column=0, columnspan=6, pady=3)
        self.entry.focus_set()

        tk.Button(self.master, text='7', width=3,
                  command=lambda: self.input(7)).grid(row=1, column=0)
        tk.Button(self.master, text='8', width=3,
                  command=lambda: self.input(8)).grid(row=1, column=1)
        tk.Button(self.master, text='9', width=3,
                  command=lambda: self.input(9)).grid(row=1, column=2)

        tk.Button(self.master, text='4', width=3,
                  command=lambda: self.input(4)).grid(row=2, column=0)
        tk.Button(self.master, text='5', width=3,
                  command=lambda: self.input(5)).grid(row=2, column=1)
        tk.Button(self.master, text='6', width=3,
                  command=lambda: self.input(6)).grid(row=2, column=2)

        tk.Button(self.master, text='1', width=3,
                  command=lambda: self.input(1)).grid(row=3, column=0)
        tk.Button(self.master, text='2', width=3,
                  command=lambda: self.input(2)).grid(row=3, column=1)
        tk.Button(self.master, text='3', width=3,
                  command=lambda: self.input(3)).grid(row=3, column=2)

        tk.Button(self.master, text='0', width=3,
                  command=lambda: self.input(0)).grid(row=4, column=0)
        tk.Button(self.master, text='.', width=3,
                  command=lambda: self.input('.')).grid(row=4, column=1)

        tk.Button(self.master, text='x', width=3,
                  command=lambda: self.input('x')).grid(row=1, column=3)
        tk.Button(self.master, text='-', width=3,
                  command=lambda: self.input('-')).grid(row=2, column=3)
        tk.Button(self.master, text='+', width=3,
                  command=lambda: self.input('+')).grid(row=3, column=3)
        tk.Button(self.master, text='÷', width=3,
                  command=lambda: self.input('÷')).grid(row=4, column=3)

        tk.Button(self.master, text='AC', width=3,
                  command=lambda: self.clear_all()).grid(row=1, column=4)
        tk.Button(self.master, text='C', width=3,
                  command=lambda: self.clear_one()).grid(row=1, column=5)

        tk.Button(self.master, text='=', width=6,
                  command=self.equals).grid(row=4, column=4, columnspan=2)

create_widgetsは、計算機のインターフェイスと各ボタンの値や役割を決める関数です。

35行目で、初期化でインスタンス化したmenu_barを継承したtk.Menuのインスタンスをfile_menuとしています。

36行目と37行目で、ファイルメニューを作っているのですが、36行目ではfile_manuに終了(quit)するcommandを追加して、Exitと表示できるようにlabelを指定します。

37行目は、メニューバーにFileと表示して、展開したメニューに1行前で定義したfile_menuExit)を表示できるようにします。

39行目で入力欄を表示する位置(rowcolumn)と長さ(columnspan)と余白(pady)を指定して、40行目のforcus.setで確定しています。

42行目から85行目で、計算機に表示するボタンとクリックされた時にinputに渡す値や演算子、処理する関数(clear_allclear_oneequals)を定義しています。

コードの実行

root = tk.Tk()
app = Application(master=root)
app.mainloop()

最後にrootを作成して、rootを継承したApplicationインスタンスを作成して、mainloopでプログラムが終了するまで起動したままにしています。

作成した計算機を使って計算した動画がこちらです。

まとめ

あまりの眠さに耐えられず、2日がかりになってしまいましたが、計算機がきちんと動くとおもしろいんですよね。

コード自体は、酒井さんのコードを写経したものですが、少しだけ変更したところもあります。

Udemy講師 酒井さん プログラミング Python

元になるサンプルコードがあれば、そのコードを使って、少しずつ変更してみればどこがどうなるのかわかってくるので、どんどんコードをカスタマイズしたり、関数を付け足したりしてみてください。

こんなコードがサラッと書けるようになれば、もっとプログラミングが楽しくなってくると思うので、頑張ってPython学習を継続していこうと思います。

ということで、明日もGood Python!