实现一个计算器(二)
上一次实现了命令行式的计算器.
这次用python实现一个窗口,
把计算器的代码翻译过来:
1 patterns = { 2 '+': r'(\+)' , 3 '-': r'(-)' , 4 '*': r'(\*)' , 5 '/': r'(/)' , 6 '(': r'(\()' , 7 ')': r'(\))' , 8 'int':r'((\+|-)?\d+(\.\d+)?)' 9 } 10 class Parse(object): 11 def __init__(self, buf): 12 self.buf = buf 13 self.value = self.expr2() 14 def expr2(self): 15 value = self.expr1() 16 while 1: 17 if self.test('+'): 18 self.match('+') 19 value += self.expr1() 20 elif self.test('-'): 21 self.match('-') 22 value -= self.expr1() 23 else: 24 break 25 return value 26 def expr1(self): 27 value = self.expr() 28 while 1: 29 if self.test('*'): 30 self.match('*') 31 value *= self.expr() 32 elif self.test('/'): 33 self.match('/') 34 value /= self.expr() 35 else: 36 break 37 return value 38 def expr(self): 39 if self.test('int'): 40 return self.match('int') 41 elif self.test('('): 42 self.match('(') 43 value = self.expr2() 44 self.match(')') 45 return value 46 else: 47 raise Exception("ERROR") 48 def test(self, name): 49 if re.match(patterns[name], self.buf): 50 return 1 51 else: 52 return 0 53 def match(self, name): 54 m = re.match(patterns[name], self.buf) 55 if m: 56 self.buf = self.buf[len(m.group(0)):] 57 if name == 'int': 58 return float(m.group(1)) 59 Exception('cannot parse "'+name+'" out')
用pyqt超级简单.100多行就完成了
1 import sys 2 import itertools 3 import re 4 from PyQt4 import QtGui,QtCore 5 6 patterns = { 7 '+': r'(\+)' , 8 '-': r'(-)' , 9 '*': r'(\*)' , 10 '/': r'(/)' , 11 '(': r'(\()' , 12 ')': r'(\))' , 13 'int':r'((\+|-)?\d+(\.\d+)?)' 14 } 15 class Parse(object): 16 def __init__(self, buf): 17 self.buf = buf 18 self.value = self.expr2() 19 def expr2(self): 20 value = self.expr1() 21 while 1: 22 if self.test('+'): 23 self.match('+') 24 value += self.expr1() 25 elif self.test('-'): 26 self.match('-') 27 value -= self.expr1() 28 else: 29 break 30 return value 31 def expr1(self): 32 value = self.expr() 33 while 1: 34 if self.test('*'): 35 self.match('*') 36 value *= self.expr() 37 elif self.test('/'): 38 self.match('/') 39 value /= self.expr() 40 else: 41 break 42 return value 43 def expr(self): 44 if self.test('int'): 45 return self.match('int') 46 elif self.test('('): 47 self.match('(') 48 value = self.expr2() 49 self.match(')') 50 return value 51 else: 52 raise Exception("ERROR") 53 def test(self, name): 54 if re.match(patterns[name], self.buf): 55 return 1 56 else: 57 return 0 58 def match(self, name): 59 m = re.match(patterns[name], self.buf) 60 if m: 61 self.buf = self.buf[len(m.group(0)):] 62 if name == 'int': 63 return float(m.group(1)) 64 Exception('cannot parse "'+name+'" out') 65 def calc(buf): 66 try: 67 p = Parse(str(buf)) 68 if p.buf: 69 return "ERROR" 70 return p.value 71 except Exception: 72 return "ERROR" 73 def log(buf): 74 f = open("calc.log","a") 75 f.write(buf+"\n") 76 f.close() 77 78 class Example(QtGui.QWidget): 79 def __init__(self): 80 super(Example, self).__init__() 81 self.initUI() 82 self.initData() 83 def initUI(self): 84 self.setWindowTitle('grid layout') 85 names = ['(', ')', 'back', 'clear', '7', '8', '9', '/', 86 '4', '5', '6', '*', '1', '2', '3', '-','0', '.', '=', '+'] 87 grid = QtGui.QGridLayout() 88 self.text = QtGui.QLineEdit() 89 self.text.setFocusPolicy(QtCore.Qt.NoFocus) 90 grid.addWidget(self.text,0,0,1,4) 91 pos = list(itertools.product(range(1,6), range(4))) 92 for j,i in enumerate(names): 93 button = QtGui.QPushButton(i) 94 self.connect(button, QtCore.SIGNAL('clicked()'), self.deal) 95 grid.addWidget(button, pos[j][0], pos[j][1]) 96 self.setLayout(grid) 97 def initData(self): 98 self.oldtexts = [] 99 def deal(self): 100 curtext = self.text.text() 101 text = self.sender().text() 102 if text == 'back': 103 if self.oldtexts: 104 self.text.setText(self.oldtexts.pop()) 105 elif text == 'clear': 106 self.text.setText("") 107 self.oldtexts.append(curtext) 108 elif text == '=': 109 ans = str(calc(curtext)) 110 log(curtext+" = "+ans) 111 self.text.setText(ans) 112 self.oldtexts.append(curtext) 113 else: 114 self.text.setText(curtext+text) 115 self.oldtexts.append(curtext) 116 117 app = QtGui.QApplication(sys.argv) 118 ex = Example() 119 ex.show() 120 sys.exit(app.exec_())
最后用pyinstall打包, 运行
pyinstaller -F calc.py && dist/calc
哈, 瞬间感觉高级了许多.