恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Python PyQt5由入门到精通超详细篇
首页
资讯中心
/
Python PyQt5由入门到精通超详细篇
Python PyQt5由入门到精通超详细篇
发布时间:2026/10/8 19:37:23
前言先把标题里的「由入门到精通」说明白这不是一个技术等级而是一句宣传语PyQt 的能力没有「入门」和「精通」两套 API只有「用得对不对」的区别。本文的目标很实在——把 PyQt5 从「建个窗口」到「写出一个能用的带菜单、能打开保存文件的小编辑器」这条路径讲清楚。PyQt5 是 Qt 5 的 Python 绑定第三方库需要pip install PyQt5官方文档写明它要求Python 3.5 或更高。本机没有安装环境所以代码只能逐行推演。具体 API 与参数以 PyQt5 官方文档为准——本文保证结构、类名、方法名与官方文档一致不保证每个可选参数的默认值都背下来了。学习 PyQt5 最容易走的弯路有两个。第一把「窗口」和「控件」混为一谈Qt 里QWidget是一切可视控件的基类既可以当独立窗口也可以当别人的子控件真正带「菜单栏 工具栏 状态栏 中心部件」框架的是QMainWindow。第二以为事件绑定要写回调注册表其实 Qt 用的是信号与槽——控件发信号你把可调用对象连上去。一、三层结构QApplication、QWidget、布局QApplication ── 全局唯一初始化 Qt、拥有事件循环└── QMainWindow或 QWidget── 窗口本身├── layoutQVBoxLayout / QGridLayout ...── 排列规则│ └── 各种控件QLabel、QLineEdit、QTextEdit、QPushButton ...└── menuBar / statusBar ── QMainWindow 自带的框架QApplication一个进程只需要一个app.exec()才是事件循环的入口。布局对象负责在窗口缩放时重新计算控件几何是 Qt 里「不用绝对坐标」的实现。二、信号与槽Qt 的事件模型Qt 不用「登记回调表」的写法而是让控件发出信号signal你把槽slot可以是任意可调用对象连上去# 适用于 Python 3.5需 pip install PyQt5第三方库button.clicked.connect(self.on_click) # clicked 是 QPushButton 的信号action.triggered.connect(self.open_file) # QAction 的 triggered 信号文档里QPushButton在鼠标点击、空格键或快捷键激活时发出clicked()QAction发出triggered(checkedFalse)。connect返回一个连接对象要断开时调它的disconnect()。信号可以连接到普通函数、方法、lambda也能一个信号连多个槽。三、从入门示例说起一个窗口加一个按钮# 适用于 Python 3.5需 pip install PyQt5第三方库import sysfrom PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QVBoxLayout, QWidgetclass Counter(QWidget):def __init__(self):super().__init__()self.setWindowTitle(计数器)self.count 0self.label QLabel(0)self.button QPushButton(加一)self.button.clicked.connect(self.increment)layout QVBoxLayout()layout.addWidget(self.label)layout.addWidget(self.button)self.setLayout(layout)def increment(self):self.count 1self.label.setText(str(self.count))def main():app QApplication(sys.argv)window Counter()window.show()sys.exit(app.exec_()) # PyQt5 既有 exec() 也有 exec_()if __name__ __main__:main()注意QLabel.setText()只接受字符串所以这里要写str(self.count)直接传整数会报类型错。QVBoxLayout()是纵向布局addWidget依次把控件加进去setLayout把它设为窗口的顶层布局。exec_()是 PyQt5 里exec()的别名——这一点后面会讲到它在 PyQt6 里已经被移除。四、进阶QMainWindow 菜单 文件读写QMainWindow提供一个标准应用框架菜单栏menuBar()、状态栏statusBar()、以及一个中心部件setCentralWidget()。下面这个迷你记事本把菜单、文件对话框、消息框都串起来。# 适用于 Python 3.5需 pip install PyQt5第三方库import sysfrom PyQt5.QtWidgets import (QApplication, QFileDialog, QMainWindow, QMessageBox, QTextEdit,)class Notepad(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle(迷你记事本)self.resize(600, 400)self.editor QTextEdit()self.setCentralWidget(self.editor) # 设为窗口中心部件file_menu self.menuBar().addMenu(文件)self.add_action(file_menu, 打开, CtrlO, self.open_file, 打开一个文本文件)self.add_action(file_menu, 保存, CtrlS, self.save_file, 保存到文本文件)file_menu.addSeparator()self.add_action(file_menu, 退出, CtrlQ, self.close, 退出程序)self.statusBar().showMessage(就绪)def add_action(self, menu, text, shortcut, slot, tip):action menu.addAction(text)action.setShortcut(shortcut)action.setStatusTip(tip) # 鼠标悬停时显示在状态栏action.triggered.connect(slot)return actiondef open_file(self):path, _selected_filter QFileDialog.getOpenFileName(self, 打开文件, , 文本文件 (*.txt);;所有文件 (*))if not path: # 用户点了取消返回空字符串returntry:with open(path, r, encodingutf-8) as fp:self.editor.setPlainText(fp.read())except OSError as exc:QMessageBox.warning(self, 打开失败, str(exc))returnself.statusBar().showMessage(f已打开{path})def save_file(self):path, _selected_filter QFileDialog.getSaveFileName(self, 保存文件, , 文本文件 (*.txt))if not path:returntry:with open(path, w, encodingutf-8) as fp:fp.write(self.editor.toPlainText())except OSError as exc:QMessageBox.warning(self, 保存失败, str(exc))returnself.statusBar().showMessage(f已保存{path})def closeEvent(self, event): # 关闭窗口时的事件钩子answer QMessageBox.question(self, 确认, 确定要退出吗,QMessageBox.Yes | QMessageBox.No, QMessageBox.No,)if answer QMessageBox.Yes:event.accept()else:event.ignore()def main():app QApplication(sys.argv)window Notepad()window.show()sys.exit(app.exec_())if __name__ __main__:main()逐行推演几个官方文档能佐证的细节。QFileDialog.getOpenFileName(parent, caption, directory, filter)是静态方法返回一个元组(文件名, 选中的过滤器)用户取消时文件名为空字符串所以先判空再操作这是必须的。QMessageBox.question(parent, title, text, buttons, defaultButton)同样返回一个StandardButton用它和QMessageBox.Yes比较即可QMessageBox.warning/information也属于同一组静态便利函数。QTextEdit.toPlainText()返回纯文本字符串setPlainText(str)写入纯文本如果你的目标是富文本要用toHtml()/setHtml()两种格式不要混用。closeEvent(event)是控件收到关闭请求时的钩子必须调用event.accept()或event.ignore()之一来决定是否真的关闭否则行为不确定。五、进阶到实战要补的几块布局的选择。QVBoxLayout/QHBoxLayout是线性布局QGridLayout是网格布局addWidget(widget, row, column)还能用setColumnStretch(列号, 权重)让某列伸缩QFormLayout适合「标签 输入框」的表单。布局可以嵌套把一个布局addLayout进另一个布局。样式。Qt 支持类似 CSS 的样式表通过widget.setStyleSheet(...)设置它有自己的选择器与属性名体系写法与网页 CSS 不完全一样具体属性以 Qt 样式表文档为准。线程。和工作线程打交道用QThread或QRunnable。铁律是工作线程不要直接碰控件要把结果通过信号发回主线程由主线程更新界面。PyQt5 与 PyQt6 的衔接。如果你打算日后升级先记住这几点差异省得将来大面积返工项目PyQt5PyQt6事件循环app.exec_()也可exec()只能app.exec()具名枚举可直接写Qt.AlignCenter必须全限定Qt.AlignmentFlag.AlignCenterqApp全局对象有已移除Python 版本要求3.53.9常见坑点❌ 把QLabel.setText(123)传个整数进去。✅setText只接受字符串先str(...)转换。❌ 忘记调用window.show()或app.exec_()。✅ 不show()窗口不可见不exec_()事件循环不启动、窗口一闪即没。❌ 在槽函数里跑长循环或同步网络请求。✅ 槽由事件循环调用长占用会让界面假死耗时任务交给QThread结果用信号发回主线程。❌ 在子线程里直接调用setText等控件方法。✅ 控件只在主线程更新跨线程通过信号槽投递。❌QFileDialog.getOpenFileName返回值当成单个字符串用。✅ 它返回二元组(文件名, 过滤器)并且用户取消时文件名为空字符串必须先判空。❌closeEvent里既不accept()也不ignore()。✅ 两者必居其一否则关闭行为不确定。❌ 用open()读写文件不写encoding。✅ 显式写encodingutf-8否则默认编码随平台变化中文跨平台易乱码。❌ 把 PyQt5 教程直接套到 PyQt6 上。✅ 先查版本差异表exec_已移除、具名枚举要全限定名照抄会报AttributeError。总结阶段关键内容起步QApplicationQWidget 布局 show()exec_()事件信号与槽signal.connect(slot)应用框架QMainWindowmenuBar()/statusBar()/setCentralWidget()文件与提示QFileDialog返回元组、QMessageBox静态便利函数进阶布局嵌套、样式表、QThread线程规则升级预备记住 PyQt5 与 PyQt6 的枚举与exec_差异「由入门到精通」不需要学两套东西而是把同一条链路走深先把窗口和控件弄清楚再吃透信号与槽最后补上布局、样式、线程这三块。做到这一步你写出来的就已经是一个能用的桌面程序而不是一个演示用的空窗口了。