作者:张大鹏
时间:2025-11-05
标签:Python、PyQt5、GUI、桌面开发、实战教程
在桌面应用开发中,计算器
它涉及到图形界面设计、事件绑定、信号槽机制、布局管理等核心概念。
今天我们将使用 PyQt5 (同样适用于 PyQt6)一步步实现一个可用的计算器程序,从 UI 布局到功能逻辑完整讲解。
最终效果如下:
| 项目依赖 | 说明 | | ---
| Python 3.8+
| PyQt5 | 图形界面开发框架 | | Qt Designer(可选) | 可视化 UI 设计工具 |
安装命令:
pip install PyQt5
我们将项目组织如下:
pyqt_calculator/
│
├── main.py
├── calculator.ui
└── ui_calculator.py
我们先手动创建一个简单的界面,不依赖 Qt Designer。
from PyQt5.QtWidgets import QApplication, QWidget, QGridLayout, QPushButton, QLineEdit, QVBoxLayout
from PyQt5.QtCore import Qt
import sys
class Calculator(QWidget): def __init__(self): super().__init__() self.setWindowTitle("PyQt 计算器") self.setFixedSize(300, 400) self.init_ui()
def init_ui(self): self.display = QLineEdit() self.display.setAlignment(Qt.AlignRight) self.display.setReadOnly(True) self.display.setStyleSheet("font-size: 24px; padding: 10px;")
buttons = { '7': (0, 0), '8': (0, 1), '9': (0, 2), '/': (0, 3), '4': (1, 0), '5': (1, 1), '6': (1, 2), '*': (1, 3), '1': (2, 0), '2': (2, 1), '3': (2, 2), '-': (2, 3), '0': (3, 0), '.': (3, 1), 'C': (3, 2), '+': (3, 3), '=': (4, 0, 1, 4) }
grid = QGridLayout() for text, pos in buttons.items(): button = QPushButton(text) button.setStyleSheet("font-size: 20px; height: 50px;") if len(pos) == 2: grid.addWidget(button, pos[0], pos[1]) else: grid.addWidget(button, pos[0], pos[1], pos[2], pos[3]) button.clicked.connect(self.on_button_clicked)
layout = QVBoxLayout() layout.addWidget(self.display) layout.addLayout(grid) self.setLayout(layout)
def on_button_clicked(self): sender = self.sender().text() current = self.display.text()
if sender == "C": self.display.clear() elif sender == "=": try: result = str(eval(current)) self.display.setText(result) except Exception: self.display.setText("Error") else: self.display.setText(current + sender)
if __name__ == "__main__": app = QApplication(sys.argv) window = Calculator() window.show() sys.exit(app.exec_())
运行后即可看到一个基础的计算器界面。
许多用户习惯直接使用键盘输入,我们可以重写 keyPressEvent 方法:
def keyPressEvent(self, event):
key = event.key()
if key == Qt.Key_Return or key == Qt.Key_Enter:
self.on_button_clicked()
elif key == Qt.Key_Backspace:
self.display.setText(self.display.text()[:-1])
else:
text = event.text()
if text.isdigit() or text in ['+', '-', '*', '/', '.']:
self.display.setText(self.display.text() + text)
这样计算器即可同时响应键盘输入。
直接使用 eval() 虽然简单,但存在安全风险。我们可以使用 Python 内置的 ast 模块安全地解析表达式。
import ast
import operator as op
operators = { ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul, ast.Div: op.truediv }
def safe_eval(expr): node = ast.parse(expr, mode='eval').body def _eval(node): if isinstance(node, ast.Num): return node.n elif isinstance(node, ast.BinOp): return operators[type(node.op)](_eval(node.left), _eval(node.right)) else: raise TypeError(node) return _eval(node)
替换掉 eval(current) 部分即可更安全地计算。
使用 Qt Style Sheet (QSS) 进行样式美化:
self.setStyleSheet("""
QWidget {
background-color: #2E3440;
}
QLineEdit {
background: #3B4252;
color: #ECEFF4;
border: none;
border-radius: 5px;
}
QPushButton {
background-color: #4C566A;
color: #ECEFF4;
border-radius: 8px;
}
QPushButton:hover {
background-color: #5E81AC;
}
QPushButton:pressed {
background-color: #81A1C1;
}
""")
界面将呈现出类似现代深色主题的视觉效果。
当应用开发完成后,我们可以使用 pyinstaller 打包为可执行文件:
pip install pyinstaller
pyinstaller -F -w main.py
生成的可执行文件在 dist/ 目录中。
这个项目的核心结构可以进一步扩展:
通过这些改善,你可以将这个小项目打磨成一个完整的专业级桌面工具。
通过本篇实战,我们掌握了以下关键技能:
PyQt 的强劲不仅在于能做出“好看的界面”,更在于它与 Python 的生态融合:你可以轻松把它扩展成数据可视化工具、AI 模型控制台、图像处理前端等等。
下一步,不妨试着给这个计算器加上图表或语音输入功能,体验 PyQt 真正的扩展性。