实现一个计算器(二)

上一次实现了命令行式的计算器.

这次用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')
View Code

 

用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_())
View Code

 

最后用pyinstall打包, 运行

pyinstaller -F calc.py && dist/calc

 

哈, 瞬间感觉高级了许多.

 

posted @ 2017-01-11 12:53  backinfile  阅读(305)  评论(0编辑  收藏  举报