Python tkinter简易计算器实现
emm,前人的代码让我受益匪浅,那么也希望我的作品能帮助到你们吧。废话不多说,直接上代码。
import tkinter as tk
from tkinter import messagebox, colorchooser, simpledialog
from decimal import *
#初始化主界面
def screen(root):
root.geometry("220x270")
root["bg"] = "white"
#菜单栏函数
def help_info():
tk.messagebox.showinfo("帮助", "有问题请直接发邮件到2804578334@qq.com, 竭诚为你服务。")
def digit_set():
i = tk.simpledialog.askinteger(title = "请输入保留位数", prompt = "请输入整数")
calculator.re_dg = int(i)
def color():
c = tk.colorchooser.askcolor()
calculator["bg"] = c[1]
root["bg"] = c[1]
#设置菜单
def main_menu():
menubar = tk.Menu(root)
menu_setting = tk.Menu(menubar)
menubar.add_cascade(label = "settings", menu = menu_setting)
menu_setting.add_command(label = "color", command = color)
menu_other = tk.Menu(menu_setting)
menu_setting.add_cascade(label = "other", menu = menu_other)
menu_other.add_command(label = "reserve_digit", command = digit_set)
menubar.add_command(label = "help", command = help_info)
root["menu"] = menubar
class Calculator(tk.Frame):
def __init__(self, master = None):
tk.Frame.__init__(self,master)
self.pack()
self.set_all()
self.status = "input"
self.re_dg = 10
self["bg"] = "white"
def set_all(self):
self.v1 = tk.StringVar()
self.pre_input = tk.Entry(self, textvariable = self.v1)
self.pre_input.grid(row = 0, column = 0, columnspan = 8, padx = 3, pady = 5)
self.v2 = tk.StringVar()
self.cur_input = tk.Entry(self, textvariable = self.v2)
self.cur_input.grid(row = 1, column = 0, columnspan = 8, padx = 3, pady = 5)
tk.Button(self, text = "del", fg = "OrangeRed", command = self.delete_one).grid(row = 2, column = 0, columnspan = 2, sticky = tk.E + tk.W, padx = 3, pady = 5)
tk.Button(self, text = "(", command = lambda : self.press("(")).grid(row = 2, column = 2, columnspan = 2, sticky = tk.E + tk.W, padx = 3, pady = 5)
tk.Button(self, text = ")", command = lambda : self.press(")")).grid(row = 2, column = 4, columnspan = 2, sticky = tk.E + tk.W, padx = 3, pady = 5)
tk.Button(self, text = "/", command = lambda : self.press("/")).grid(row = 2, column = 6, columnspan = 2, sticky = tk.E + tk.W, padx = 3, pady = 5)
tk.Button(self, text = "1", command = lambda : self.press("1"), bg = "Black", fg = "white").grid(row = 3, column = 0, columnspan = 2, sticky = tk.E + tk.W, padx = 3, pady = 5)
tk.Button(self, text = "2", command = lambda : self.press("2"), bg = "Black", fg = "white").grid(row = 3, column = 2, columnspan = 2, sticky = tk.E + tk.W, padx = 3, pady = 5)
tk.Button(self, text = "3", command = lambda : self.press("3"), bg = "Black", fg = "white").grid(row = 3, column = 4, columnspan = 2, sticky = tk.E + tk.W, padx = 3, pady = 5)
tk.Button(self, text = "*", command = lambda : self.press("*")).grid(row = 3, column = 6, columnspan = 2, sticky = tk.E + tk.W, padx = 3, pady = 5)
tk.Button(self, text = "4", command = lambda : self.press("4"), bg = "Black", fg = "white").grid(row = 4, column = 0, columnspan = 2, sticky = tk.E + tk.W, padx = 3, pady = 5)
tk.Button(self, text = "5", command = lambda : self.press("5"), bg = "Black", fg = "white").grid(row = 4, column = 2, columnspan = 2, sticky = tk.E + tk.W, padx = 3, pady = 5)
tk.Button(self, text = "6", command = lambda : self.press("6"), bg = "Black", fg = "white").grid(row = 4, column = 4, columnspan = 2, sticky = tk.E + tk.W, padx = 3, pady = 5)
tk.Button(self, text = "-", command = lambda : self.press("-")).grid(row = 4, column = 6, columnspan = 2, sticky = tk.E + tk.W, padx = 3, pady = 5)
tk.Button(self, text = "7", command = lambda : self.press("7"), bg = "Black", fg = "white").grid(row = 5, column = 0, columnspan = 2, sticky = tk.E + tk.W, padx = 3, pady = 5)
tk.Button(self, text = "8", command = lambda : self.press("8"), bg = "Black", fg = "white").grid(row = 5, column = 2, columnspan = 2, sticky = tk.E + tk.W, padx = 3, pady = 5)
tk.Button(self, text = "9", command = lambda : self.press("9"), bg = "Black", fg = "white").grid(row = 5, column = 4, columnspan = 2, sticky = tk.E + tk.W, padx = 3, pady = 5)
tk.Button(self, text = "+", command = lambda : self.press("+")).grid(row = 5, column = 6, columnspan = 2, sticky = tk.E + tk.W, padx = 3, pady = 5)
tk.Button(self, text = ".", command = lambda : self.press(".")).grid(row = 6, column = 0, columnspan = 2, sticky = tk.E + tk.W, padx = 3, pady = 5)
tk.Button(self, text = "0", command = lambda : self.press("0"), bg = "Black", fg = "white").grid(row = 6, column = 2, columnspan = 2, sticky = tk.E + tk.W, padx = 3, pady = 5)
tk.Button(self, text = "=", command = self.calculate ,bg = "OrangeRed", fg = "white").grid(row = 6, column = 4, columnspan = 4,sticky = tk.E + tk.W, padx = 3, pady = 5)
def press(self, new):
if self.status == "output":
past = self.cur_input.get()
self.v1.set(past)
self.v2.set("")
self.status = "input"
string = self.cur_input.get()
string += new
self.v2.set(string)
def delete_one(self):
new = self.cur_input.get()[:-1]
self.v2.set(new)
def calculate(self):
def precede(a, b):
"""Compare the prior of operator a and b"""
# the prior of operator
prior = (
# '+' '-' '*' '/' '(' ')' '^' '#'
('>', '>', '<', '<', '<', '>', '<', '>'), # '+'
('>', '>', '<', '<', '<', '>', '<', '>'), # '-'
('>', '>', '>', '>', '<', '>', '<', '>'), # '*'
('>', '>', '>', '>', '<', '>', '<', '>'), # '/'
('<', '<', '<', '<', '<', '=', '<', ' '), # '('
('>', '>', '>', '>', ' ', '>', '>', '>'), # ')'
('>', '>', '>', '>', '<', '>', '>', '>'), # '^'
('<', '<', '<', '<', '<', ' ', '<', '=') # '#'
)
# operator to index of prior[8][8]
char2num = {
'+': 0,
'-': 1,
'*': 2,
'/': 3,
'(': 4,
')': 5,
'^': 6,
'#': 7
}
return prior[char2num[a]][char2num[b]]
def operate(a, b, operator):
"""Operate [a operator b]"""
if operator == '+':
ans = a + b
elif operator == '-':
ans = a - b
elif operator == '*':
ans = a * b
elif operator == '/':
if b == 0:
ans = "VALUE ERROR"
else:
ans = a / b
elif operator == '^':
if a == 0 and b == 0:
ans = "VALUE ERROR"
else:
ans = a ** b
return ans
def calc(exp):
"""Calculate the ans of exp"""
exp += '#'
operSet = "+-*/^()#"
stackOfOperator, stackOfNum = ['#'], []
pos, ans, index, length = 0, 0, 0, len(exp)
while index < length:
e = exp[index]
if e in operSet:
# calc according to the prior
topOperator = stackOfOperator.pop()
compare = precede(topOperator, e)
if compare == '>':
try:
b = stackOfNum.pop()
a = stackOfNum.pop()
except:
tk.messagebox.showinfo("提示", "格式错误")
ans = operate(a, b, topOperator)
if ans == "VALUE ERROR":
tk.messagebox.showinfo("提示", "值错误")
else:
stackOfNum.append(ans)
elif compare == '<':
stackOfOperator.append(topOperator)
stackOfOperator.append(e)
index += 1
elif compare == '=':
index += 1
elif compare == ' ':
tk.messagebox.showinfo("提示", "格式错误")
else:
# get the next num
pos = index
while not exp[index] in operSet:
index += 1
temp = exp[pos:index]
# delete all 0 of float in the end
last = index - 1
if '.' in temp:
while exp[last] == '0':
last -= 1
temp = exp[pos:last + 1]
try:
temp = Decimal(temp)
except:
tk.messagebox.showinfo("提示", "输入错误")
stackOfNum.append(temp)
if len(stackOfNum) == 1 and stackOfOperator == []:
return stackOfNum.pop()
else:
tk.messagebox.showinfo("提示", "输入错误")
if self.status == "input":
exp = self.cur_input.get()
getcontext().prec = self.re_dg
self.v1.set(exp)
self.v2.set(calc(exp))
self.status = "output"
if __name__ == "__main__":
root = tk.Tk()
root.title("计算器")
screen(root)
main_menu()
calculator = Calculator(root)
calculator.mainloop()
最后的代码效果是这样的: