运行环境:python3.9+wxPython4.2.1
运行效果:
按下等于号,输出:
按下R键,保留两位小数
键盘布局与逻辑分离,添加删除功能一般功能或修改键盘布局只需要更改词典的顺序即可。添加特殊功能时则需要将队对应的逻辑也写一下。
import re
import wx
class MCalculator(wx.Frame):
pos_x, pos_y = 10, 70
btn_w, btn_h = 50, 50
x_interval = 83
y_interval = 83
layout_dict = [
{
"C": "special",
"➗": "operator[/]",
"✖": "operator[*]",
"⬅": "special"
},
{
"7": "number",
"8": "number",
"9": "number",
"➖": "operator[-]"
},
{
"4": "number",
"5": "number",
"6": "number",
"➕": "operator[+]"
},
{
"1": "number",
"2": "number",
"3": "number",
"=": "special"
},
{
"0": "number",
".": "number",
"(": "operator[(]",
")": "operator[)]"
},
{
"^": "operator[**]",
"R": "special"
}
]
layout = None
numbers = None
operators = None
@classmethod
def initialize_class_attr(cls):
regex_eq = r'operator\[(.*?)\]'
cls.layout = [[c for c in cls.layout_dict[i]] for i in range(len(cls.layout_dict))]
cls.numbers = [key for d in cls.layout_dict for key, value in d.items() if value == "number"]
cls.operators = {
key: re.search(regex_eq, value).group(1)
for d in cls.layout_dict
for key, value in d.items()
if re.match(regex_eq, value)
}
pass
def __init__(self):
wx.Frame.__init__(self, None, title="简单计算器", pos=(100, 100), size=(340, 600))
self.pl = wx.Panel(self, pos=(0, 0), size=(300, 600))
# self.pl.SetBackgroundColour(wx.RED)
self.entry = wx.TextCtrl(self.pl, pos=(10, 10), size=(300, 50), style=wx.TE_RIGHT | wx.TE_READONLY)
self.btns = [[None for _ in range(len(self.layout[i]))] for i in range(len(self.layout))]
self.special_function_dict = {
"=": self.On_btn_eq,
"⬅": self.On_btn_back,
"C": self.On_btn_clear,
"R": self.On_do_round
}
for i in range(len(self.layout)):
for j in range(len(self.layout[i])):
# 创建按键
self.btns[i][j] = wx.Button(
self.pl,
label=self.layout[i][j],
pos=(self.pos_x + j * self.x_interval, self.pos_y + i * self.y_interval),
size=(self.btn_w, self.btn_h))
# 为数字键绑定事件
if self.layout[i][j] in self.numbers:
self.Bind(
wx.EVT_BUTTON,
lambda _, lbl=self.layout[i][j]: self.entry.AppendText(lbl),
self.btns[i][j])
# 为运算按键绑定事件
if self.layout[i][j] in self.operators:
self.Bind(
wx.EVT_BUTTON,
lambda _, lbl=self.operators[self.layout[i][j]]: self.entry.AppendText(lbl),
self.btns[i][j])
# 为其他特殊功能绑定事件
if self.layout[i][j] in self.special_function_dict:
self.Bind(
wx.EVT_BUTTON,
self.special_function_dict[self.layout[i][j]],
self.btns[i][j])
def Handle_exception(self, text, e):
self.entry.SetValue(f"【算式:{text}】发生错误!{str(e)}")
def On_btn_eq(self, event):
text = ""
try:
text = self.entry.GetValue()
result = str(eval(text))
self.entry.SetValue(result)
except Exception as e:
self.Handle_exception(text, e)
def On_btn_back(self, event):
text = self.entry.GetValue()
self.entry.SetValue(text[:-1])
def On_btn_clear(self, event):
self.entry.Clear()
def On_do_round(self, event):
text = ""
try:
text = self.entry.GetValue()
result = str(round(float(text), 2))
self.entry.SetValue(result)
except Exception as e:
self.Handle_exception(text, e)
if __name__ == '__main__':
app = wx.App()
MCalculator.initialize_class_attr()
frame = MCalculator()
frame.Show()
app.MainLoop()