如何用PyQt5实现一个简易计算器应用
在本篇博客中,我将详细介绍如何使用PyQt5构建一个简易计算器应用。这个计算器能够执行基本的数学运算(如加法、减法、乘法、除法),并且能计算sin和cos值。用户可以通过图形界面输入数字、运算符,按下“=”按钮进行计算,还可以清空输入框,计算三角函数。
1. 项目介绍
在现代应用开发中,图形用户界面(GUI)是提升用户体验的重要部分。Python作为一门易学且功能强大的编程语言,拥有丰富的GUI开发框架,而PyQt5是其中最为流行的一种。
通过本项目,我们将创建一个简易计算器,主要功能包括:
支持数字输入。
支持基本的数学运算(加法、减法、乘法、除法)。
支持计算
sin和cos值(基于角度)。支持结果的显示和错误处理。
本计算器的UI设计将使用PyQt5的设计器工具来创建,而业务逻辑将由Python脚本处理。
2. 项目结构
本项目由两部分组成:
UI设计部分:通过PyQt5的界面设计工具(
pyuic5)生成UI界面。功能实现部分:通过Python编写程序逻辑来处理用户输入和计算。
2.1 设计UI
首先,我们需要使用PyQt5的界面设计工具来设计UI。UI包括数字按钮、运算符按钮、清空按钮、计算按钮和输入框。我们将通过界面上的按钮来模拟用户输入,输入框(lineEdit)用于显示当前输入内容或计算结果。
设计思路:
计算器界面包含数字按钮(0-9)、常用运算符(+、-、*、/)、三角函数(sin、cos)、清空按钮和计算按钮(=)。
输入框用于显示用户的输入和计算结果。
通过Qt Designer生成一个UI文件,我们可以使用pyuic5将其转化为Python代码。设计的界面如下所示:
顶部:标题“简易计算机”。
中部:一个
lineEdit,用于显示输入或结果。下方:按钮区,包括数字按钮、运算符按钮、三角函数按钮、清空按钮和计算按钮。
2.2 编写逻辑代码
UI设计完成后,我们将重点编写逻辑代码部分。主要包括以下几个功能:
数字和运算符输入:点击数字按钮或运算符按钮,将按钮上的内容添加到
lineEdit中。等号按钮:点击
=按钮时,计算输入的数学表达式。sin和cos按钮:点击sin或cos按钮时,计算输入数字的三角函数值。清空按钮:点击
clean按钮时,清空输入框。
3. 步骤一:准备开发环境
3.1 安装PyQt5
在开始编写代码之前,首先需要确保已经安装了PyQt5。可以通过以下命令安装:
pip install PyQt5 3.2 安装其他依赖
我们还需要安装math模块用于数学计算。这个模块是Python的标准库,不需要额外安装。
4. 步骤二:设计UI界面
在PyQt5中,GUI设计有两种方式:一种是通过Python代码手动布局,另一种是通过Qt Designer图形化工具设计并生成UI文件。在这里,我们使用Qt Designer来设计UI界面。
4.1 使用Qt Designer设计界面
打开Qt Designer,选择
Main Window模板。拖动并放置控件:
一个
QLabel用来显示标题“简易计算机”。一个
QLineEdit用来显示用户输入和计算结果。多个
QPushButton,分别表示数字按钮、运算符按钮、清空按钮、计算按钮等。
保存UI文件,命名为
win.ui。
4.2 转换为Python代码
使用PyQt5提供的工具pyuic5,将.ui文件转化为Python代码:
pyuic5 -o win.py win.ui
这样,我们就生成了win.py,它包含了UI的布局和控件。
5. 步骤三:编写逻辑代码
接下来,我们编写应用程序的逻辑部分。首先,我们需要从win.py导入UI界面,然后实现按键的功能。
5.1 继承UI类并添加功能
在新的Python脚本中,我们定义一个PyQtMainEntry类,它继承自QMainWindow和Ui_MainWindow。在该类中,我们实现每个按钮的点击事件,并处理输入框内容。
import math
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMainWindow
from win import Ui_MainWindow # 导入UI类class PyQtMainEntry(QMainWindow, Ui_MainWindow):def __init__(self):super().__init__()self.setupUi(self)self.expression = "" # 用来存储lineEdit的表达式def update_lineEdit(self, value):current_text = self.lineEdit.text()self.lineEdit.setText(current_text + value)# 数字和运算符按钮def number1(self):self.update_lineEdit("1")# 其他数字和运算符按钮类似...def getall(self):expression = self.lineEdit.text()try:result = eval(expression) # 使用eval来计算表达式self.lineEdit.setText(str(result))except:self.lineEdit.setText("ERROR") # 出现错误时显示ERRORdef waysin(self):value = self.lineEdit.text()try:num = float(value)self.lineEdit.setText(str(math.sin(math.radians(num)))) # 计算sin值except:self.lineEdit.setText("ERROR")def waycos(self):value = self.lineEdit.text()try:num = float(value)self.lineEdit.setText(str(math.cos(math.radians(num)))) # 计算cos值except:self.lineEdit.setText("ERROR")
5.2 事件连接
在UI文件中,已为每个按钮定义了clicked.connect()事件。我们需要确保这些按钮与相应的功能函数连接,以便用户点击时触发正确的操作。
self.pushButton_1.clicked.connect(self.number1) # 数字1按钮
self.pushButton_2.clicked.connect(self.number2) # 数字2按钮
self.pushButton_15.clicked.connect(self.getall) # 等号按钮
self.pushButton_17.clicked.connect(self.waysin) # sin按钮
self.pushButton_18.clicked.connect(self.waycos) # cos按钮
6. 步骤四:运行程序
在程序的最后,我们运行QApplication事件循环,启动计算器应用:
if __name__ == "__main__":app = QtWidgets.QApplication(sys.argv)window = PyQtMainEntry()window.show()sys.exit(app.exec_())
7.完整代码展示
win.py:
# -*- coding: utf-8 -*-# Form implementation generated from reading ui file 'win.ui'
#
# Created by: PyQt5 UI code generator 5.15.11
#
# 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, QtWidgetsclass Ui_MainWindow(object):def setupUi(self, MainWindow):MainWindow.setObjectName("MainWindow")MainWindow.resize(800, 600)self.centralwidget = QtWidgets.QWidget(MainWindow)self.centralwidget.setObjectName("centralwidget")self.label = QtWidgets.QLabel(self.centralwidget)self.label.setGeometry(QtCore.QRect(240, 40, 271, 51))self.label.setStyleSheet("font: 40pt \"Agency FB\";")self.label.setObjectName("label")self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)self.lineEdit.setGeometry(QtCore.QRect(180, 130, 391, 51))self.lineEdit.setStyleSheet("font: 24pt \"Agency FB\";")self.lineEdit.setObjectName("lineEdit")self.pushButton = QtWidgets.QPushButton(self.centralwidget)self.pushButton.setGeometry(QtCore.QRect(110, 240, 75, 23))self.pushButton.setObjectName("pushButton")self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_2.setGeometry(QtCore.QRect(230, 240, 75, 23))self.pushButton_2.setObjectName("pushButton_2")self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_3.setGeometry(QtCore.QRect(360, 240, 75, 23))self.pushButton_3.setObjectName("pushButton_3")self.pushButton_4 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_4.setGeometry(QtCore.QRect(110, 290, 75, 23))self.pushButton_4.setObjectName("pushButton_4")self.pushButton_5 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_5.setGeometry(QtCore.QRect(230, 290, 75, 23))self.pushButton_5.setObjectName("pushButton_5")self.pushButton_6 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_6.setGeometry(QtCore.QRect(360, 290, 75, 23))self.pushButton_6.setObjectName("pushButton_6")self.pushButton_7 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_7.setGeometry(QtCore.QRect(110, 340, 75, 23))self.pushButton_7.setObjectName("pushButton_7")self.pushButton_8 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_8.setGeometry(QtCore.QRect(230, 340, 75, 23))self.pushButton_8.setObjectName("pushButton_8")self.pushButton_9 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_9.setGeometry(QtCore.QRect(360, 340, 75, 23))self.pushButton_9.setObjectName("pushButton_9")self.pushButton_10 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_10.setGeometry(QtCore.QRect(110, 400, 75, 23))self.pushButton_10.setObjectName("pushButton_10")self.pushButton_11 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_11.setGeometry(QtCore.QRect(480, 290, 75, 23))self.pushButton_11.setObjectName("pushButton_11")self.pushButton_12 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_12.setGeometry(QtCore.QRect(480, 350, 75, 23))self.pushButton_12.setObjectName("pushButton_12")self.pushButton_13 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_13.setGeometry(QtCore.QRect(480, 240, 75, 23))self.pushButton_13.setObjectName("pushButton_13")self.pushButton_14 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_14.setGeometry(QtCore.QRect(590, 290, 75, 23))self.pushButton_14.setObjectName("pushButton_14")self.pushButton_15 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_15.setGeometry(QtCore.QRect(590, 350, 75, 23))self.pushButton_15.setObjectName("pushButton_15")self.pushButton_16 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_16.setGeometry(QtCore.QRect(480, 400, 75, 23))self.pushButton_16.setObjectName("pushButton_16")self.pushButton_17 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_17.setGeometry(QtCore.QRect(230, 400, 75, 23))self.pushButton_17.setObjectName("pushButton_17")self.pushButton_18 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_18.setGeometry(QtCore.QRect(360, 400, 75, 23))self.pushButton_18.setObjectName("pushButton_18")MainWindow.setCentralWidget(self.centralwidget)self.menubar = QtWidgets.QMenuBar(MainWindow)self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))self.menubar.setObjectName("menubar")MainWindow.setMenuBar(self.menubar)self.statusbar = QtWidgets.QStatusBar(MainWindow)self.statusbar.setObjectName("statusbar")MainWindow.setStatusBar(self.statusbar)self.retranslateUi(MainWindow)self.pushButton_14.clicked.connect(self.lineEdit.clear) # type: ignoreself.pushButton_2.clicked.connect(MainWindow.number2) # type: ignoreself.pushButton_3.clicked.connect(MainWindow.number3) # type: ignoreself.pushButton.clicked.connect(MainWindow.number1) # type: ignoreself.pushButton_4.clicked.connect(MainWindow.number4) # type: ignoreself.pushButton_5.clicked.connect(MainWindow.number5) # type: ignoreself.pushButton_6.clicked.connect(MainWindow.number6) # type: ignoreself.pushButton_7.clicked.connect(MainWindow.number7) # type: ignoreself.pushButton_8.clicked.connect(MainWindow.number8) # type: ignoreself.pushButton_9.clicked.connect(MainWindow.number9) # type: ignoreself.pushButton_10.clicked.connect(MainWindow.number0) # type: ignoreself.pushButton_15.clicked.connect(MainWindow.getall) # type: ignoreself.pushButton_13.clicked.connect(MainWindow.way1) # type: ignoreself.pushButton_11.clicked.connect(MainWindow.way2) # type: ignoreself.pushButton_12.clicked.connect(MainWindow.way3) # type: ignoreself.pushButton_16.clicked.connect(MainWindow.way4) # type: ignoreself.pushButton_18.clicked.connect(MainWindow.waycos) # type: ignoreself.pushButton_17.clicked.connect(MainWindow.waysin) # type: ignoreQtCore.QMetaObject.connectSlotsByName(MainWindow)def retranslateUi(self, MainWindow):_translate = QtCore.QCoreApplication.translateMainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))self.label.setText(_translate("MainWindow", "简易计算机"))self.pushButton.setText(_translate("MainWindow", "1"))self.pushButton_2.setText(_translate("MainWindow", "2"))self.pushButton_3.setText(_translate("MainWindow", "3"))self.pushButton_4.setText(_translate("MainWindow", "4"))self.pushButton_5.setText(_translate("MainWindow", "5"))self.pushButton_6.setText(_translate("MainWindow", "6"))self.pushButton_7.setText(_translate("MainWindow", "7"))self.pushButton_8.setText(_translate("MainWindow", "8"))self.pushButton_9.setText(_translate("MainWindow", "9"))self.pushButton_10.setText(_translate("MainWindow", "0"))self.pushButton_11.setText(_translate("MainWindow", "-"))self.pushButton_12.setText(_translate("MainWindow", "*"))self.pushButton_13.setText(_translate("MainWindow", "+"))self.pushButton_14.setText(_translate("MainWindow", "clean"))self.pushButton_15.setText(_translate("MainWindow", "="))self.pushButton_16.setText(_translate("MainWindow", "/"))self.pushButton_17.setText(_translate("MainWindow", "sin"))self.pushButton_18.setText(_translate("MainWindow", "cos"))
main.py(主函数)
import mathfrom PyQt5 import QtCore, QtGui, QtWidgets # 导入PyQt5的主要模块
from PyQt5.QtCore import * # 导入QtCore模块的所有内容,用于核心功能
from PyQt5.QtGui import * # 导入QtGui模块的所有内容,用于图形功能
from PyQt5.QtWidgets import QFileDialog, QMainWindow, QMessageBox # 导入QtWidgets模块中的一些特定类
'''QFileDialog可以帮助用户选择文件路径
QMainWindow则是创建具有菜单、工具栏和状态栏的主窗口的起点。
QMessageBox可以用于向用户显示提示或警告信息'''from win import Ui_MainWindow # 导入UI类,这个类包含了你的主窗口设计
import sys # 导入系统模块,用于访问命令行参数和系统相关功能# 导入 math 库用于数学计算
class PyQtMainEntry(QMainWindow, Ui_MainWindow):def __init__(self):super().__init__()self.setupUi(self)self.expression = "" # 用来存储lineEdit的表达式# 更新lineEdit内容(用于按钮点击)def update_lineEdit(self, value):current_text = self.lineEdit.text()self.lineEdit.setText(current_text + value)# 处理数字和运算符按钮点击def number1(self):self.update_lineEdit("1")def number2(self):self.update_lineEdit("2")def number3(self):self.update_lineEdit("3")def number4(self):self.update_lineEdit("4")def number5(self):self.update_lineEdit("5")def number6(self):self.update_lineEdit("6")def number7(self):self.update_lineEdit("7")def number8(self):self.update_lineEdit("8")def number9(self):self.update_lineEdit("9")def number0(self):self.update_lineEdit("0")def way1(self): # 加号按钮self.update_lineEdit("+")def way2(self): # 减号按钮self.update_lineEdit("-")def way3(self): # 乘号按钮self.update_lineEdit("*")def way4(self): # 除号按钮self.update_lineEdit("/")# 清空lineEdit内容def clear(self):self.lineEdit.clear()# 计算表达式结果def getall(self):expression = self.lineEdit.text()try:result = eval(expression) # 使用eval来计算表达式self.lineEdit.setText(str(result))except:self.lineEdit.setText("ERROR") # 出现错误时显示ERROR# 计算sin值(仅适用于纯数字)def waysin(self):value = self.lineEdit.text()try:num = float(value)self.lineEdit.setText(str(math.sin(math.radians(num)))) # 将角度转换为弧度并计算sinexcept:self.lineEdit.setText("ERROR")# 计算cos值(仅适用于纯数字)def waycos(self):value = self.lineEdit.text()try:num = float(value)self.lineEdit.setText(str(math.cos(math.radians(num)))) # 将角度转换为弧度并计算cosexcept:self.lineEdit.setText("ERROR")if __name__ == "__main__":app = QtWidgets.QApplication(sys.argv) # 创建应用程序实例window = PyQtMainEntry() # 创建主窗口实例window.show() # 显示主窗口sys.exit(app.exec_()) # 进入事件循环,并确保在退出时清理8. 总结
通过本篇博客,我们从思路到操作步骤,详细介绍了如何使用PyQt5实现一个简易计算器。该计算器支持数字输入、基本运算、三角函数计算以及错误处理。整个开发过程从UI设计到功能实现都进行了详细讲解,帮助大家了解如何用PyQt5开发简单的GUI应用。
如果你已经掌握了这些基本操作,后续可以尝试更复杂的功能和设计,比如增加内存功能、支持多步计算、或者加入更多的数学函数等。希望这篇博客能为你开发GUI应用提供一些启发!
