sleeplikelog
@sleeplikelog (夏輝 荒川)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

四則演算のできるGUIを作りたい

解決したいこと

はじめまして、pythonを勉強しているプログラミング初心者のものです。
京大の公開している演習テキストhttps://repository.kulib.kyoto-u.ac.jp/dspace/handle/2433/245698
に沿って演習を解いていて、電卓のGUIを作るにあたって、四則演算をする(+を押せば足し算を、/を押せば割り算をする)コードを書きたく、ひとまず足し算と割り算をするコードを描いてみたのですが、+,/のどちらを押しても同じ値を返してしまいます。解決策を教えていただきたいです。よろしくお願いします。

該当するソースコード

import tkinter as tk

#計算昨日のための変数とイベント用の関数定義

#2項演算のモデル
#入力中の数字

current_number = 0

#第一項

first_term = 0

#第二項

second_term = 0

#結果
result_1 = 0

result_2 = 0

def do_plus():
    "+ キーが押されたときの計算動作, 第一項の設定と入力中の数字のクリア"

    global current_number
    global first_term

    first_term=first_term + current_number
    current_number=0

def do_devision():
    "/ キーが押されたときの計算動作, 第一項の設定と入力中の数字のクリア"

    global current_number
    global first_term

    first_term=first_term/current_number
    current_number=0


def do_eq():
    "= キーが押されたときの計算動作, 第二項の設定、加算または除算の実施、入力中の数字のクリア"

    global second_term
    global result_1
    global result_2
    global current_number
    second_term=current_number
    result_1 = first_term+second_term
    result_2 = first_term/second_term
    current_number = 0

# 数字キーのCall Back 関数
def key1():
    key(1)

def key2():
    key(2)

def key3():
    key(3)

def key4():
    key(4)

def key5():
    key(5)

def key6():
    key(6)

def key7():
    key(7)

def key8():
    key(8)

def key9():
    key(9)

def key0():
    key(0)

#数字キーを一括処理する関数

def key(n):
    global current_number
    current_number=current_number*10+n
    show_number(current_number)


def clear():
    global current_number
    current_number = 0
    show_number(current_number)

def plus():
    do_plus()
    show_number(current_number)

def devision():
    do_devision()
    show_number(current_number)

def eq():
    do_eq()
    show_number(result_1 or result_2)

def show_number(num):
    e.delete(0,tk.END)
    e.insert(0,str(num))

#tkinter での画面の構成

root = tk.Tk()
f = tk.Frame(root)
f.grid()

#ウィジェットの作成

b1 = tk.Button(f,text='1',command=key1)
b2 = tk.Button(f,text='2',command=key2)
b3 = tk.Button(f,text='3',command=key3)
b4 = tk.Button(f,text='4',command=key4)
b5 = tk.Button(f,text='5',command=key5)
b6 = tk.Button(f,text='6',command=key6)
b7 = tk.Button(f,text='7',command=key7)
b8 = tk.Button(f,text='8',command=key8)
b9 = tk.Button(f,text='9',command=key9)
b0 = tk.Button(f,text='0',command=key0)
bc = tk.Button(f,text='C',command=clear)
bp = tk.Button(f,text='+',command=plus)
bd = tk.Button(f,text='/',command=devision)
be = tk.Button(f,text="=",command=eq)

#Grid 型ジオメトリマネージャによるウィジェットの
# 割付

b1.grid(row=3,column=0)
b2.grid(row=3,column=1)
b3.grid(row=3,column=2)
b4.grid(row=2,column=0)
b5.grid(row=2,column=1)
b6.grid(row=2,column=2)
b7.grid(row=1,column=0)
b8.grid(row=1,column=1)
b9.grid(row=1,column=2)
b0.grid(row=4,column=0)
bc.grid(row=1,column=3)
be.grid(row=4,column=3)
bp.grid(row=2,column=3)
bd.grid(row=3,column=3)

#数値を表示するウィジェット
e = tk.Entry(f)
e.grid(row=0, column=0,columnspan=4)
clear()

#ここからGUIがスタート
root.mainloop()

自分で試したこと

上記コードのようにeqを押した時に演算に応じた結果がでることを意図して足し算の結果をresult_1, 割り算の結果をresult_2としましたが、割り算をしても足し算の結果(あるいは足し算をしても割り算した結果)を返してしまいます。

0

3Answer

少し大きめの修正をしてみました。
= を押したときに 加算処理 あるいは 除算処理 をするので、それらの計算関数を変数に記憶しておいて、= が押されたときに記憶した計算関数を呼び出すようにしました。
いちいち global を書くのが面倒なので、class number をデータ領域にしました。こうすれば global を書かなくて済みます。

import tkinter as tk


class number:
    """2項演算のモデル"""

    # 入力中の数字
    current = 0

    # 第一項
    first = 0

    # 第二項
    second = None

    # 演算子
    op = None


def op_plus(a, b):
    return a + b


def op_division(a, b):
    return a / b


def digit(n):
    number.current = number.current * 10 + n
    if number.op is None:
        number.first = number.current
    else:
        number.second = number.current
    show_number(number.current)


def clear():
    number.current = 0
    number.first = 0
    number.second = None
    number.op = None
    show_number(number.current)


def calculate():
    if number.second is not None:
        number.first = number.op(number.first, number.second)
    number.second = None
    number.current = 0
    number.op = None
    show_number(number.first)


def plus():
    calculate()
    number.op = op_plus


def division():
    calculate()
    number.op = op_division


def eq():
    calculate()


def show_number(num):
    e.delete(0, tk.END)
    e.insert(0, str(num))

# tkinter での画面の構成

root = tk.Tk()
f = tk.Frame(root)
f.grid()

# ウィジェットの作成

b1 = tk.Button(f, text='1', command=lambda: digit(1))
b2 = tk.Button(f, text='2', command=lambda: digit(2))
b3 = tk.Button(f, text='3', command=lambda: digit(3))
b4 = tk.Button(f, text='4', command=lambda: digit(4))
b5 = tk.Button(f, text='5', command=lambda: digit(5))
b6 = tk.Button(f, text='6', command=lambda: digit(6))
b7 = tk.Button(f, text='7', command=lambda: digit(7))
b8 = tk.Button(f, text='8', command=lambda: digit(8))
b9 = tk.Button(f, text='9', command=lambda: digit(9))
b0 = tk.Button(f, text='0', command=lambda: digit(0))
bc = tk.Button(f, text='C', command=clear)
bp = tk.Button(f, text='+', command=plus)
bd = tk.Button(f, text='/', command=division)
be = tk.Button(f, text="=", command=eq)

# Grid 型ジオメトリマネージャによるウィジェットの
# 割付

b1.grid(row=3, column=0)
b2.grid(row=3, column=1)
b3.grid(row=3, column=2)
b4.grid(row=2, column=0)
b5.grid(row=2, column=1)
b6.grid(row=2, column=2)
b7.grid(row=1, column=0)
b8.grid(row=1, column=1)
b9.grid(row=1, column=2)
b0.grid(row=4, column=0)
bc.grid(row=1, column=3)
be.grid(row=4, column=3)
bp.grid(row=2, column=3)
bd.grid(row=3, column=3)

# 数値を表示するウィジェット
e = tk.Entry(f)
e.grid(row=0, column=0, columnspan=4)
clear()

# ここからGUIがスタート
root.mainloop()
1Like

Comments

  1. @sleeplikelog

    Questioner

    @shiracamusさん

    コメントいただきありがとうございます。私の質問が説明不足でお手間をお掛けしてしまいすみませんでした。教えて頂いた書き方で試してみたのですが、(下記がフルコード)正しい計算結果が出ませんでした。(clearが効かずに延々と足し算をしてる?)もし気づく点ありましたらご教示いただけると幸いです。

    また、classについてもまだ学習しておりませんでした。Qiitaにpythonのクラスの書き方の記事がありましたので勉強します。ありがとうございます。

    ```:python
    print('hello world')

    import tkinter as tk

    #計算昨日のための変数とイベント用の関数定義

    #2項演算のモデル
    #入力中の数字

    current_number = 0

    #第一項

    first_term = 0

    #第二項

    second_term = 0

    #結果
    result_1 = 0

    result_2 = 0

    def do_plus():
    "+ キーが押されたときの計算動作, 第一項の設定と入力中の数字のクリア"

    global current_number
    global first_term

    first_term=first_term + current_number
    current_number=0

    def do_devision():
    "/ キーが押されたときの計算動作, 第一項の設定と入力中の数字のクリア"

    global current_number
    global first_term

    first_term=first_term/current_number
    current_number=0


    def do_eq():
    "= キーが押されたときの計算動作, 第二項の設定、加算または除算の実施、入力中の数字のクリア"

    global second_term
    global result_1
    global result_2
    global current_number
    second_term=current_number
    result_1 = first_term+second_term
    result_2 = first_term/second_term
    current_number = 0

    # 数字キーのCall Back 関数
    def key1():
    key(1)

    def key2():
    key(2)

    def key3():
    key(3)

    def key4():
    key(4)

    def key5():
    key(5)

    def key6():
    key(6)

    def key7():
    key(7)

    def key8():
    key(8)

    def key9():
    key(9)

    def key0():
    key(0)

    #数字キーを一括処理する関数

    def key(n):
    global current_number
    current_number=current_number*10+n
    show_number(current_number)


    def clear():
    global current_number
    current_number = 0
    show_number(current_number)

    def plus():
    do_plus()
    show_number(current_number)

    def devision():
    do_devision()
    show_number(current_number)

    def eq():
    do_eq()
    show_number(result_1 or result_2)

    def show_number(num):
    e.delete(0,tk.END)
    e.insert(0,str(num))

    #tkinter での画面の構成

    root = tk.Tk()
    f = tk.Frame(root)
    f.grid()

    #ウィジェットの作成

    b1 = tk.Button(f,text='1',command=key1)
    b2 = tk.Button(f,text='2',command=key2)
    b3 = tk.Button(f,text='3',command=key3)
    b4 = tk.Button(f,text='4',command=key4)
    b5 = tk.Button(f,text='5',command=key5)
    b6 = tk.Button(f,text='6',command=key6)
    b7 = tk.Button(f,text='7',command=key7)
    b8 = tk.Button(f,text='8',command=key8)
    b9 = tk.Button(f,text='9',command=key9)
    b0 = tk.Button(f,text='0',command=key0)
    bc = tk.Button(f,text='C',command=clear)
    bp = tk.Button(f,text='+',command=plus)
    bd = tk.Button(f,text='/',command=devision)
    be = tk.Button(f,text="=",command=eq)

    #Grid 型ジオメトリマネージャによるウィジェットの
    # 割付

    b1.grid(row=3,column=0)
    b2.grid(row=3,column=1)
    b3.grid(row=3,column=2)
    b4.grid(row=2,column=0)
    b5.grid(row=2,column=1)
    b6.grid(row=2,column=2)
    b7.grid(row=1,column=0)
    b8.grid(row=1,column=1)
    b9.grid(row=1,column=2)
    b0.grid(row=4,column=0)
    bc.grid(row=1,column=3)
    be.grid(row=4,column=3)
    bp.grid(row=2,column=3)
    bd.grid(row=3,column=3)

    #数値を表示するウィジェット
    e = tk.Entry(f)
    e.grid(row=0, column=0,columnspan=4)
    clear()

    #ここからGUIがスタート
    root.mainloop()
    ```


  2. コードブロックの3連バッククオート直後のコロンを削除してください。
    コードは質問を変種して貼りなおせませんか?
    私のコードのように色付けされて表示されるはずです。
  3. インデントがなくなっていて、実行することができません。
    実行確認したコードに入れ替えていただけますか?
    最初の質問内容の右上にある「・・・」をクリックすると、質問を編集するメニューがありませんか?
  4. @sleeplikelog

    Questioner

    おっしゃっている意味にようやく気づきました。。(もともとの質問を編集しろということだったのですね、、)申し訳ありません。
    元の質問に当初の全コードを記載しました。お時間ありましたら何卒お願いします。
  5. 回答のコードを入れ替えました。
    ちょっと大きな改造をしました。
  6. 2+3+4= などの連続計算ができなかったのを修正しました。
  7. @sleeplikelog

    Questioner

    @shiracamus さん
    回答ありがとうございます!
    自分のと比較して読み解いてみます。
    丁寧にご回答いただきありがとうございました。
calc.py
def do_sum(first_num, second_num):
    return int(first_num) + int(second_num);

def do_divide(first_num, second_num):
    return int(first_num) / int(second_num);

def show_result(first_num, second_num, method, result):
    print ('%.2f %s %.2f = %.2f' % (
        float(first_num)
        , method
        , float(second_num)
        , float(result)
        )
    )

if __name__ == '__main__':
    result = 0
    first_num = input('Input first Number:\t')
    method = input('Input + or / :\t\t')
    second_num = input('Input second Number:\t')
    if method == '+':
        result = do_sum(first_num, second_num)
    elif method == '/':
        result = do_divide(first_num, second_num)
    show_result(first_num, second_num, method, result)
$ python3 calc.py 
Input first Number:	3
Input + or / :		+
Input second Number:	9
3.00 + 9.00 = 12.00
$ python3 calc.py 
Input first Number:	9
Input + or / :		/
Input second Number:	2
9.00 / 2.00 = 4.50
1Like

@shiracamusさん @kkent030315

コメントありがとうございます。回答への返信という形では正しく色付きで表示されなかったのですが、別の投稿にすると正しく表示されました。:bow:

よろしければこちらにアドバイスいただけますと幸いです。よろしくお願いします。



import tkinter as tk

#計算昨日のための変数とイベント用の関数定義

#2項演算のモデル
#入力中の数字

current_number = 0

#第一項

first_term = 0

#第二項

second_term = 0

#結果
result_1 = 0

result_2 = 0

def do_plus():
"+ キーが押されたときの計算動作, 第一項の設定と入力中の数字のクリア"

global current_number
global first_term

first_term=first_term + current_number
current_number=0

def do_devision():
"/ キーが押されたときの計算動作, 第一項の設定と入力中の数字のクリア"

global current_number
global first_term

first_term=first_term/current_number
current_number=0


def do_eq():
"= キーが押されたときの計算動作, 第二項の設定、加算または除算の実施、入力中の数字のクリア"

global second_term
global result_1
global result_2
global current_number
second_term=current_number
result_1 = first_term+second_term
result_2 = first_term/second_term
current_number = 0

# 数字キーのCall Back 関数
def key1():
key(1)

def key2():
key(2)

def key3():
key(3)

def key4():
key(4)

def key5():
key(5)

def key6():
key(6)

def key7():
key(7)

def key8():
key(8)

def key9():
key(9)

def key0():
key(0)

#数字キーを一括処理する関数

def key(n):
global current_number
current_number=current_number*10+n
show_number(current_number)


def clear():
global current_number
current_number = 0
show_number(current_number)

def plus():
do_plus()
show_number(current_number)

def devision():
do_devision()
show_number(current_number)

def eq():
do_eq()
show_number(result_1 or result_2)

def show_number(num):
e.delete(0,tk.END)
e.insert(0,str(num))

#tkinter での画面の構成

root = tk.Tk()
f = tk.Frame(root)
f.grid()

#ウィジェットの作成

b1 = tk.Button(f,text='1',command=key1)
b2 = tk.Button(f,text='2',command=key2)
b3 = tk.Button(f,text='3',command=key3)
b4 = tk.Button(f,text='4',command=key4)
b5 = tk.Button(f,text='5',command=key5)
b6 = tk.Button(f,text='6',command=key6)
b7 = tk.Button(f,text='7',command=key7)
b8 = tk.Button(f,text='8',command=key8)
b9 = tk.Button(f,text='9',command=key9)
b0 = tk.Button(f,text='0',command=key0)
bc = tk.Button(f,text='C',command=clear)
bp = tk.Button(f,text='+',command=plus)
bd = tk.Button(f,text='/',command=devision)
be = tk.Button(f,text="=",command=eq)

#Grid 型ジオメトリマネージャによるウィジェットの
# 割付

b1.grid(row=3,column=0)
b2.grid(row=3,column=1)
b3.grid(row=3,column=2)
b4.grid(row=2,column=0)
b5.grid(row=2,column=1)
b6.grid(row=2,column=2)
b7.grid(row=1,column=0)
b8.grid(row=1,column=1)
b9.grid(row=1,column=2)
b0.grid(row=4,column=0)
bc.grid(row=1,column=3)
be.grid(row=4,column=3)
bp.grid(row=2,column=3)
bd.grid(row=3,column=3)

#数値を表示するウィジェット
e = tk.Entry(f)
e.grid(row=0, column=0,columnspan=4)
clear()

#ここからGUIがスタート
root.mainloop()
0Like

Your answer might help someone💌