废话
该案例包含两个类:
- 计算器是一个Calculator部件,包含所有计算器功能
- Button部件用于每个计算机按钮,它由QToolButton派生
我们先校验计算器,然后再看按钮
定义计算器类
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys
class Calculator(QWidget):
def __init__(self):
super(Calculator, self).__init__()
app = QApplication(sys.argv)
cal = Calculator
cal.show()
app.exec_()
- 相关槽(cpp)
private slots:
void digitClicked();
void unaryOperatorClicked();
void additiveOperatorClicked();
void multiplicativeOperatorClicked();
void equalClicked();
void pointClicked();
void changeSignClicked();
void backspaceClicked();
void clear();
void clearAll();
void clearMemory();
void readMemory();
void setMemory();
void addToMemory();
按钮根据他们的行为分类组合,例如所有数字按钮在当前的操作数追加一个数字。为此我们将各类按钮连接到相同的槽(例如digitClicked()),类目有:数字,一元运算符、加减法运算符、乘除法运算符,其他的按钮有他们自己的槽。
def createButton(self, text, member):
pass
def abortOperation(self):
pass
def calculate(self, rightOperand, pendingOperator):
pass
- createButton()函数作为部件构造器的一部分
- abortOperation() 当出现被零除或负数平方根时被调用
- calculate()提供二进制操作(+, -, ×, ÷)
self.sumInMemory = 0
self.sumSoFar = 0
self.factorSoFar = 0
self.pendingAdditiveOperator = ''
self.pendingMultiplicativeOperator = ''
self.waitingForOperand = True
- sumInMemory包含计算器内存中存储的值
- sumSoFar存储目前累积值,当用户点击‘=’,它被重计算并显示出来,清除所有并重置sumSoFar为零
- 当做乘除法时,factorSoFar用来存储临时值
- pendingAdditiveOperator存储用户点击的最终加法操作符
- pendingMultiplicativeOperator存储用户点击的最终乘法操作符
- 当计算器希望用户输入一个操作符时,waitingForOperand为真
加法和乘法操作符对待不同,是因为他们有不同的优先级,例如1 + 2 ÷ 3可理解为1 + (2 ÷ 3),因为‘÷’比‘+’优先级高。
一元运算符(像平发根)不需要特别的操作,当已知运算数并点击运算符按钮时,他们可以立即应用。
实现计算器部件类
构造器内,我们初始化计算器状态
self.sumInMemory = 0.0
self.sumSoFar = 0.0
self.factorSoFar = 0.0
self.pendingAdditiveOperator = ''
self.pendingMultiplicativeOperator = ''
self.waitingForOperand = True
self.display = QLineEdit('0')
self.display.setReadOnly(True)
self.display.setAlignment(Qt.AlignRight)
self.display.setMaxLength(15)
QLineEdit代表计算器的显示,并设置一些它的属性,我们特别设置它为只读。
self.NumDigitButton = range(10)
self.digitButton = list(self.NumDigitButton)
for i in self.NumDigitButton:
self.digitButton[i] = self.creatButton(str(i), self.digitClicked)
self.pointButton = self.creatButton('.', self.pointClicked)
self.changeSignButton = self.creatButton('\302\261', self.changeSignClicked)
self.backspaceButoon = self.creatButton('BackSpace', self.backspaceClicked)
self.clearButton = self.creatButton('Clear', self.clear)
self.clearAllButton = self.creatButton('Clear All', self.clearAll)
self.clearMemoryButton = self.creatButton('MC', self.clearMemory)
self.readMemoryButton = self.creatButton('MR', self.readMemory)
self.setMemoryButton = self.creatButton('MS', self.setMemory)
self.addToMemoryButton = self.creatButton('M+', self.addToMemory)
self.divisionButton = self.creatButton('\303\267', self.multiplicativeOperatorClicked)
self.timesButton = self.creatButton('\303\227', self.multiplicativeOperatorClicked)
self.minusButton = self.creatButton('-', self.additiveOperatorClicked)
self.plusButton = self.creatButton('+', self.additiveOperatorClicked)
self.squrareRootButton = self.creatButton('Sqrt', self.unaryOperatorClicked)
self.powerButton = self.creatButton('x\302\262', self.unaryOperatorClicked)
self.reciprocalButton = self.creatButton('1/x', self.unaryOperatorClicked)
self.equalButton = self.creatButton('=', self.equalClicked)
对每个按钮调用createButton()函数,设置相应的文本标签和按钮对应的槽。
self.mainLayout = QGridLayout()
self.mainLayout.setSizeConstraint(QLayout.SetFixedSize)
self.mainLayout.addWidget(self.display, 0, 0, 1, 6)
self.mainLayout.addWidget(self.backspaceButoon, 1, 0, 1, 2)
self.mainLayout.addWidget(self.clearButton, 1, 2, 1, 2)
self.mainLayout.addWidget(self.clearAllButton, 1, 4, 1, 2)
self.mainLayout.addWidget(self.clearMemoryButton, 2, 0)
self.mainLayout.addWidget(self.readMemoryButton, 3, 0)
self.mainLayout.addWidget(self.setMemoryButton, 4, 0)
self.mainLayout.addWidget(self.addToMemoryButton, 5, 0)
for i in self.NumDigitButton:
if i > 0:
row = ((9 - i) / 3) + 2
column = ((i - 1) % 3) + 1
self.mainLayout.addWidget(self.digitButton[i], row, column)
self.mainLayout.addWidget(self.digitButton[0], 5, 1