Tkinterで、簡易電卓を作るシリーズ④計算機能を作る

Twitterでシェア FaceBookでシェア はてなブックマークでシェア

Python - Tkinter
2018年11月22日21:14に更新(約21日前)
2018年10月6日22:02に作成(約68日前)

旧ブログからの移行記事です。

概要

Tkinterで、簡易電卓を作るシリーズの1つです。 計算処理を実装していきます。

計算機能の実装

現状では、どのボタンを押してもcalcメソッドが呼ばれるようになっています。 ここを改良する必要がありますが、その前に__init__内にインスタンスの変数を一つ追加します。

    def __init__(self, master=None):
        super().__init__(master)
        self.exp_list = ['0']  # これを足した
        self.create_style()
        self.create_widgets()

実装方法はいくつかあると思いますが、今回はできるだけシンプルにしました。

各数字、記号のボタンが押されると、self.exp_listに['1', '+', '10', '*', '5'] のように格納されていきます。=ボタンが押されれば、この'1 + 10 * 5' の文字列をeval()を使って評価し、その結果をリストに格納します。['51']のようにします。
Cボタンならば、リストの中身を['0']にします。 そして、表示欄には、このリストを' '.join()した形..つまり、'1 + 10 * 5'や、'0'、'51' のように表示させます。

*を押した後に+を押された、等の少し特殊な操作を考える必要がありますが、そこまで難しくはありません。

流れを簡単に書いてみると、以下のようになります。

    def calc(self, event):
        # 押されたボタンのテキストを取得
        char = event.widget['text']

        # 最後に押したボタンの内容
        last = self.exp_list[-1]

        if char == '=':
            print('=が押された')
        elif char == 'C':
            print('Cが押された')
        elif char in ('+', '-', '*', '/'):
            print('記号が押された')
        else:
            print('数字が押された')

        # リストに格納している式を文字列にし、画面に反映
        self.display_var.set(
            ' '.join(self.exp_list)
        )

=を押した

まずは=を押された場合を考えます。=を押された際に考えることは、最後の入力が記号だった場合です。つまり、['1', '+'] のような式だった場合、evalに渡すと怒られます。なので、最後の入力が記号だったらそれを除くようにします。

        # =ボタン(現在の式の評価)の場合
        if char == '=':
            if last in ('+', '-', '*', '/', '**', '//'): 
                self.exp_list.pop()
            exp = eval(''.join(self.exp_list))
            self.exp_list = [str(exp)]

以下の部分が、最後の入力が記号だったら、という意味になります。

if last in ('+', '-', '*', '/', '**', '//'): 

この条件分岐部分は以降の処理でも使いそうなので、モジュールの定数にしておきましょう。

# 記号をまとめた定数. if char in CALC_SYMBOLS:... のように使うために定義
CALC_SYMBOLS = ('+', '-', '*', '/', '**', '//')

コードにも反映しておきましょう。

        # =ボタン(現在の式の評価)の場合
        if char == '=':
            if last in CALC_SYMBOLS:  # ここ
                self.exp_list.pop()
            exp = eval(''.join(self.exp_list))
            self.exp_list = [str(exp)]

Cを押した場合

次にCを押した場合ですが、これは簡単です。リストの式を消去して0を入れるだけ!

        # Cボタン、内容クリア
        elif char == 'C':
            self.exp_list = ['0']

各演算記号を押した

各演算記号を押された際の処理は、少し複雑です。考えておくケースは、以下の4つです。

  1. 最後の入力が「/」で、今の入力も「/」の場合→最後の入力(exp_list[-1])を「//」に変える

  2. 最後の入力が「」で、今の入力も「」の場合→最後の入力を「**」に変える

  3. 最後の入力が演算記号で、今の入力も演算記号の場合(「/」を押された後に「+」などの場合)→最後の入力を、今入力された記号に変える

  4. それ以外(最後の入力が数値)で、今の入力も演算記→今の入力をリストの末尾に追加

//や**は、専用のボタンでも作っておけばもっと楽に作れましたが、仕方ありません。

これをコードにしてみると、以下のようになります。

        # +,-,*,/,等の記号を押した場合
        elif char in CALC_SYMBOLS:
            if last == char == '/':
                self.exp_list[-1] += '/'
            elif last == char == '*':
                self.exp_list[-1] += '*'
            elif last in CALC_SYMBOLS:
                self.exp_list[-1] = char
            else:
                self.exp_list.append(char)

数値のボタンを押した

そして、数値のボタンを押した際です。

  1. 最後の入力が0だった場合→最後の入力(exp_list[-1])を、今入力された数値にする。['0']→['1'], ['1', '+', '0']→['1', '+', '1']
  2. 最後の入力が演算記号だった場合→リストの末尾に、入力された数値を追加する。['1', '*', '5'] のようにする
  3. それ以外、最後の入力が数値で0じゃない場合→['1']を['16']のように、最後の入力にそのまま足す

コードで表すと以下のようになります。

        # それ以外、数字を押した場合
        else:
            if last == '0':
                self.exp_list[-1] = char
            elif last in CALC_SYMBOLS:
                self.exp_list.append(char)
            else:
                self.exp_list[-1] += char
Twitterでシェア FaceBookでシェア はてなブックマークでシェア

記事にコメントする