本节课,我们以所学的 Qt 的知识,来编写一个精品计算器的项目,计算器虽然是一个小项目,我们也要遵循软件工程的步骤。
可行性分析:我们用 PyQt 界面库完全可以胜任开发一个带图形界面的计算器。
需求分析:实现用户点击数字进行四则运算。
设计:用 Qt Designer 进行 UI 设计,计算逻辑放在一个类里面设计。
代码编写:先用 QtDesigner 设计 UI 界面,然后转化为 py 代码,然后再写一个计算器类,该类关联上 UI 并在该类里面做计算逻辑处理。
测试:我们用开发好的计算器程序进行四则运算测试。
运行与维护:最后交付给客户始运行维护。
首先,我们用 Qt Designer 设计一个基于 QWidget 的计算器界面,如下图所示。
我们把生成的 ui 文件转为 py 文件后,精品计算器的界面代码如下,在 Qt Designer 里面,我只设计了控件以及控件上面字体的大小。
# -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'mytest.ui' # # Created by: PyQt5 UI code generator 5.15.1 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. from PyQt5 import QtCore, QtGui, QtWidgets class Ui_Form(object): def setupUi(self, Form): Form.setObjectName("Form") Form.resize(527, 629) self.pushButton_clear = QtWidgets.QPushButton(Form) self.pushButton_clear.setGeometry(QtCore.QRect(20, 90, 91, 81)) font = QtGui.QFont() font.setPointSize(22) self.pushButton_clear.setFont(font) self.pushButton_clear.setObjectName("pushButton_clear") self.lineEdit_rst = QtWidgets.QLineEdit(Form) self.lineEdit_rst.setGeometry(QtCore.QRect(20, 10, 481, 61)) font = QtGui.QFont() font.setPointSize(22) self.lineEdit_rst.setFont(font) self.lineEdit_rst.setObjectName("lineEdit_rst") self.pushButton_link = QtWidgets.QPushButton(Form) self.pushButton_link.setGeometry(QtCore.QRect(150, 90, 351, 81)) font = QtGui.QFont() font.setPointSize(22) self.pushButton_link.setFont(font) self.pushButton_link.setCheckable(False) self.pushButton_link.setObjectName("pushButton_link") self.pushButton_7 = QtWidgets.QPushButton(Form) self.pushButton_7.setGeometry(QtCore.QRect(20, 200, 91, 81)) font = QtGui.QFont() font.setPointSize(22) self.pushButton_7.setFont(font) self.pushButton_7.setObjectName("pushButton_7") self.pushButton_9 = QtWidgets.QPushButton(Form) self.pushButton_9.setGeometry(QtCore.QRect(280, 200, 91, 81)) font = QtGui.QFont() font.setPointSize(22) self.pushButton_9.setFont(font) self.pushButton_9.setObjectName("pushButton_9") self.pushButton_8 = QtWidgets.QPushButton(Form) self.pushButton_8.setGeometry(QtCore.QRect(150, 200, 91, 81)) font = QtGui.QFont() font.setPointSize(22) self.pushButton_8.setFont(font) self.pushButton_8.setObjectName("pushButton_8") self.pushButton_divide = QtWidgets.QPushButton(Form) self.pushButton_divide.setGeometry(QtCore.QRect(410, 200, 91, 81)) font = QtGui.QFont() font.setPointSize(22) self.pushButton_divide.setFont(font) self.pushButton_divide.setObjectName("pushButton_divide") self.pushButton_multiply = QtWidgets.QPushButton(Form) self.pushButton_multiply.setGeometry(QtCore.QRect(410, 310, 91, 81)) font = QtGui.QFont() font.setPointSize(22) self.pushButton_multiply.setFont(font) self.pushButton_multiply.setObjectName("pushButton_multiply") self.pushButton_4 = QtWidgets.QPushButton(Form) self.pushButton_4.setGeometry(QtCore.QRect(20, 310, 91, 81)) font = QtGui.QFont() font.setPointSize(22) self.pushButton_4.setFont(font) self.pushButton_4.setObjectName("pushButton_4") self.pushButton_6 = QtWidgets.QPushButton(Form) self.pushButton_6.setGeometry(QtCore.QRect(280, 310, 91, 81)) font = QtGui.QFont() font.setPointSize(22) self.pushButton_6.setFont(font) self.pushButton_6.setObjectName("pushButton_6") self.pushButton_5 = QtWidgets.QPushButton(Form) self.pushButton_5.setGeometry(QtCore.QRect(150, 310, 91, 81)) font = QtGui.QFont() font.setPointSize(22) self.pushButton_5.setFont(font) self.pushButton_5.setObjectName("pushButton_5") self.pushButton_2 = QtWidgets.QPushButton(Form) self.pushButton_2.setGeometry(QtCore.QRect(150, 430, 91, 81)) font = QtGui.QFont() font.setPointSize(22) self.pushButton_2.setFont(font) self.pushButton_2.setObjectName("pushButton_2") self.pushButton_1 = QtWidgets.QPushButton(Form) self.pushButton_1.setGeometry(QtCore.QRect(20, 430, 91, 81)) font = QtGui.QFont() font.setPointSize(22) self.pushButton_1.setFont(font) self.pushButton_1.setObjectName("pushButton_1") self.pushButton_minus = QtWidgets.QPushButton(Form) self.pushButton_minus.setGeometry(QtCore.QRect(410, 430, 91, 81)) font = QtGui.QFont() font.setPointSize(22) self.pushButton_minus.setFont(font) self.pushButton_minus.setObjectName("pushButton_minus") self.pushButton_3 = QtWidgets.QPushButton(Form) self.pushButton_3.setGeometry(QtCore.QRect(280, 430, 91, 81)) font = QtGui.QFont() font.setFamily("Agency FB") font.setPointSize(22) font.setBold(False) font.setWeight(50) self.pushButton_3.setFont(font) self.pushButton_3.setIconSize(QtCore.QSize(18, 18)) self.pushButton_3.setObjectName("pushButton_3") self.pushButton_dot = QtWidgets.QPushButton(Form) self.pushButton_dot.setGeometry(QtCore.QRect(150, 530, 91, 81)) font = QtGui.QFont() font.setPointSize(22) self.pushButton_dot.setFont(font) self.pushButton_dot.setObjectName("pushButton_dot") self.pushButton_0 = QtWidgets.QPushButton(Form) self.pushButton_0.setGeometry(QtCore.QRect(20, 530, 91, 81)) font = QtGui.QFont() font.setPointSize(22) self.pushButton_0.setFont(font) self.pushButton_0.setObjectName("pushButton_0") self.pushButton_plus = QtWidgets.QPushButton(Form) self.pushButton_plus.setGeometry(QtCore.QRect(410, 530, 91, 81)) font = QtGui.QFont() font.setPointSize(22) self.pushButton_plus.setFont(font) self.pushButton_plus.setObjectName("pushButton_plus") self.pushButton_rst = QtWidgets.QPushButton(Form) self.pushButton_rst.setGeometry(QtCore.QRect(280, 530, 91, 81)) font = QtGui.QFont() font.setFamily("Agency FB") font.setPointSize(22) font.setBold(True) font.setWeight(75) self.pushButton_rst.setFont(font) self.pushButton_rst.setIconSize(QtCore.QSize(18, 18)) self.pushButton_rst.setObjectName("pushButton_rst") self.retranslateUi(Form) QtCore.QMetaObject.connectSlotsByName(Form) def retranslateUi(self, Form): _translate = QtCore.QCoreApplication.translate Form.setWindowTitle(_translate("Form", "精品计算器")) self.pushButton_clear.setText(_translate("Form", "AC")) self.pushButton_link.setText(_translate("Form", "www.birdpython.com")) self.pushButton_7.setText(_translate("Form", "7")) self.pushButton_9.setText(_translate("Form", "9")) self.pushButton_8.setText(_translate("Form", "8")) self.pushButton_divide.setText(_translate("Form", "÷")) self.pushButton_multiply.setText(_translate("Form", "×")) self.pushButton_4.setText(_translate("Form", "4")) self.pushButton_6.setText(_translate("Form", "6")) self.pushButton_5.setText(_translate("Form", "5")) self.pushButton_2.setText(_translate("Form", "2")) self.pushButton_1.setText(_translate("Form", "1")) self.pushButton_minus.setText(_translate("Form", "-")) self.pushButton_3.setText(_translate("Form", "3")) self.pushButton_dot.setText(_translate("Form", ".")) self.pushButton_0.setText(_translate("Form", "0")) self.pushButton_plus.setText(_translate("Form", "+")) self.pushButton_rst.setText(_translate("Form", "="))
设计好界面之后,然后我创建一个继承 Qwidget 的类,在该类里面做计算逻辑处理,信号槽,关联 UI 界面,设置界面属性,以及对界面上的控件设置背景色等操作。
import sys import calui from decimal import Decimal from PyQt5 import QtGui, QtCore from PyQt5.QtWidgets import QWidget, QApplication from PyQt5.QtGui import QIcon, QPalette, QBrush, QPixmap class MyWidget(QWidget): def initdata(self): # 初始化数据 self.operator = "" # 运算符 self.leftdata = "" # 左边数据 self.rightdata = "" # 右边数据 self.bcalculated = False # 有没有做运算 self.error = False # 错误的计算,比如除数为0 def initui(self): self.setFixedSize(self.width(), self.height()) # 设置窗口固定大小 self.setWindowIcon(QIcon('birdpython.png')) # 设置窗口图标 self.ui.lineEdit_rst.setText("0") # 结果栏里默认为 0 # 给窗口设置背景图片 palette = QPalette() palette.setBrush(QPalette.Background, QBrush(QPixmap("background.png"))) self.setPalette(palette) # 给链接按钮设置颜色 self.ui.pushButton_link.setStyleSheet('QPushButton {background-color: green}') def __init__(self): self.initdata() super(MyWidget, self).__init__() self.ui = calui.Ui_Form() self.ui.setupUi(self) self.initui() # 数字信号槽关联 self.ui.pushButton_1.clicked.connect(self.clicked_num) self.ui.pushButton_2.clicked.connect(self.clicked_num) self.ui.pushButton_3.clicked.connect(self.clicked_num) self.ui.pushButton_4.clicked.connect(self.clicked_num) self.ui.pushButton_5.clicked.connect(self.clicked_num) self.ui.pushButton_6.clicked.connect(self.clicked_num) self.ui.pushButton_7.clicked.connect(self.clicked_num) self.ui.pushButton_8.clicked.connect(self.clicked_num) self.ui.pushButton_9.clicked.connect(self.clicked_num) self.ui.pushButton_0.clicked.connect(self.clicked_num) # 运算 self.ui.pushButton_plus.clicked.connect(self.clicked_calculate) self.ui.pushButton_minus.clicked.connect(self.clicked_calculate) self.ui.pushButton_multiply.clicked.connect(self.clicked_calculate) self.ui.pushButton_divide.clicked.connect(self.clicked_calculate) # 官网 self.ui.pushButton_link.clicked.connect(self.clicked_link) # 归零 self.ui.pushButton_clear.clicked.connect(self.clicked_clear) # 小数点 self.ui.pushButton_dot.clicked.connect(self.clicked_dot) # 等号 self.ui.pushButton_rst.clicked.connect(self.clicked_result) def clicked_link(self): QtGui.QDesktopServices.openUrl(QtCore.QUrl('http://www.birdpython.com')) def clicked_dot(self): # 小数点 if self.bcalculated == True: # 右边数 if self.rightdata == "": self.rightdata = "0." else: self.rightdata += "." self.ui.lineEdit_rst.setText(self.rightdata) else: # 左边数 if self.leftdata == "": self.leftdata = "0." else: self.leftdata += "." self.ui.lineEdit_rst.setText(self.leftdata) def clicked_clear(self): # 清零 self.initdata() self.ui.lineEdit_rst.setText("0") # 结果栏里默认为 0 def clicked_num(self): sender = self.sender() # sender 是发射信号的按钮 if self.bcalculated == True: # 右边数 if (self.rightdata == "0" or self.rightdata == "") and sender.text() == "0": self.ui.lineEdit_rst.setText("0") else: self.rightdata += sender.text() # 右边数字 self.ui.lineEdit_rst.setText(self.rightdata) else: # 左边数 if self.ui.lineEdit_rst.text() == "0" and sender.text() == "0": self.ui.lineEdit_rst.setText("0") else: self.leftdata += sender.text() # 左边数字 self.ui.lineEdit_rst.setText(self.leftdata) def clicked_result(self): # 点击等号 if self.error: # 除数为0 self.initdata() self.error = True self.ui.lineEdit_rst.setText("除数不能为0,请归零后重新开始") else: self.ui.lineEdit_rst.setText(str(self.getresult())) def getresult(self): # 计算结果 # 把空值转为 "0" self.leftdata = self.leftdata if self.leftdata != "" else "0" self.rightdata = self.rightdata if self.rightdata != "" else "0" try: self.leftdata = Decimal(self.leftdata) self.rightdata = Decimal(self.rightdata) except: return self.leftdata if self.operator == "+": self.leftdata += self.rightdata # 左数据为运算结果 elif self.operator == "-": self.leftdata -= self.rightdata elif self.operator == "×": self.leftdata *= self.rightdata elif self.operator == "^": self.leftdata = pow(self.leftdata, self.rightdata) elif self.operator == "÷": if self.rightdata == 0: self.initdata() self.error = True return self.leftdata /= self.rightdata self.rightdata = "" self.leftdata = str(self.leftdata) return self.leftdata def clicked_calculate(self): if self.bcalculated == True: # 点击过运算和被运算的数字了 rst = str(self.getresult()) if self.error: # 除数为0 self.ui.lineEdit_rst.setText("除数不能为0,请归零后重新开始") else: self.ui.lineEdit_rst.setText(rst) sender = self.sender() # sender 是发射信号的按钮 self.operator = sender.text() self.bcalculated = True app = QApplication(sys.argv) mycal = MyWidget() mycal.show() app.exec_()
谢谢老师,学习了~~