如果你会一点 Python,但还没做过桌面图形界面(GUI),这篇教程可以带你快速上手 PyQt6。这是一篇“能直接跑、能看见结果、能继续扩展”的实战入门。
1. PyQt6 是什么?为什么值得学
PyQt6 是 Qt 在 Python 世界的绑定库,核心优势是:
- 跨平台(Windows / macOS / Linux)
- 组件丰富(按钮、表格、树、菜单、对话框、图形视图)
- 适合工具型产品、内部系统客户端、教学项目
- 对 Python 开发者非常友好
如果你正在做自动化脚本、数据处理脚本,PyQt6 可以把“命令行工具”升级成“可视化工具”。
2. 环境安装与项目结构建议
建议使用 Python 3.10+。
验证:
1
| python -c "import PyQt6; print('PyQt6 OK')"
|
推荐项目结构:
1 2 3 4 5 6
| my_pyqt6_app/ ├─ main.py ├─ ui/ ├─ services/ ├─ assets/ └─ requirements.txt
|
3. 第一个窗口:理解 QApplication 与事件循环
1 2 3 4 5 6 7 8 9
| import sys from PyQt6.QtWidgets import QApplication, QWidget
app = QApplication(sys.argv) window = QWidget() window.setWindowTitle("我的第一个 PyQt6 窗口") window.resize(520, 340) window.show() sys.exit(app.exec())
|
关键点:
QApplication:应用对象,一个进程只保留一个。
QWidget:最基础的窗口/控件父类。
app.exec():事件循环启动,界面才会响应点击、输入等行为。
4. 控件与布局:从“能显示”到“能组织”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import sys from PyQt6.QtWidgets import ( QApplication, QWidget, QVBoxLayout, QLabel, QLineEdit, QPushButton )
class DemoWindow(QWidget): def __init__(self): super().__init__() self.setWindowTitle("PyQt6 控件示例") self.resize(420, 240)
self.label = QLabel("请输入你的名字:") self.input_box = QLineEdit() self.btn = QPushButton("打招呼")
layout = QVBoxLayout() layout.addWidget(self.label) layout.addWidget(self.input_box) layout.addWidget(self.btn) self.setLayout(layout)
if __name__ == "__main__": app = QApplication(sys.argv) window = DemoWindow() window.show() sys.exit(app.exec())
|
布局是 GUI 开发里非常关键的一层:
QVBoxLayout:垂直堆叠
QHBoxLayout:水平排列
QGridLayout:网格布局
- 嵌套布局:复杂界面的标准做法
5. 信号与槽:交互逻辑的核心
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import sys from PyQt6.QtWidgets import ( QApplication, QWidget, QVBoxLayout, QLabel, QLineEdit, QPushButton )
class DemoWindow(QWidget): def __init__(self): super().__init__() self.setWindowTitle("PyQt6 信号槽示例") self.resize(420, 240)
self.label = QLabel("请输入你的名字:") self.input_box = QLineEdit() self.result = QLabel("") self.btn = QPushButton("打招呼")
self.btn.clicked.connect(self.say_hello)
layout = QVBoxLayout() layout.addWidget(self.label) layout.addWidget(self.input_box) layout.addWidget(self.btn) layout.addWidget(self.result) self.setLayout(layout)
def say_hello(self): name = self.input_box.text().strip() or "同学" self.result.setText(f"你好,{name}!欢迎学习 PyQt6")
if __name__ == "__main__": app = QApplication(sys.argv) window = DemoWindow() window.show() sys.exit(app.exec())
|
常见信号:
clicked
textChanged
currentIndexChanged
itemSelectionChanged
6. 小实战:简易待办清单(Todo)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| import sys from PyQt6.QtWidgets import ( QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton, QListWidget, QMessageBox )
class TodoApp(QWidget): def __init__(self): super().__init__() self.setWindowTitle("PyQt6 Todo") self.resize(520, 380)
self.input_box = QLineEdit() self.input_box.setPlaceholderText("输入待办事项...")
self.add_btn = QPushButton("添加") self.del_btn = QPushButton("删除选中")
self.list_widget = QListWidget()
top_layout = QHBoxLayout() top_layout.addWidget(self.input_box) top_layout.addWidget(self.add_btn)
main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addWidget(self.list_widget) main_layout.addWidget(self.del_btn) self.setLayout(main_layout)
self.add_btn.clicked.connect(self.add_item) self.del_btn.clicked.connect(self.delete_item)
def add_item(self): text = self.input_box.text().strip() if not text: QMessageBox.warning(self, "提示", "请输入内容后再添加") return self.list_widget.addItem(text) self.input_box.clear()
def delete_item(self): row = self.list_widget.currentRow() if row < 0: QMessageBox.information(self, "提示", "请先选中一条待办") return self.list_widget.takeItem(row)
if __name__ == "__main__": app = QApplication(sys.argv) window = TodoApp() window.show() sys.exit(app.exec())
|
7. 代码拆分建议:避免 main.py 越写越大
当项目稍微复杂后,建议这么拆:
ui/main_window.py:界面类
services/todo_service.py:业务逻辑
models/:数据结构
main.py:只做应用启动
这会让后续维护、测试、重构都更轻松。
8. 常见坑位与排查方法
8.1 点按钮没反应
优先排查是否正确绑定:
1
| self.btn.clicked.connect(self.on_click)
|
8.2 窗口一闪而过
通常是没有进入事件循环,或程序提前退出。
8.3 样式无效
确认你是否用的是 Qt 样式表(QSS),并检查选择器是否匹配控件对象。
9. PyQt6 与 Tkinter 的差异(快速理解)
- Tkinter:轻量、上手快、组件相对少
- PyQt6:更现代、组件更多、企业级可扩展性更强
如果你未来会做中大型桌面工具,建议优先 PyQt6。
10. 下一步学习路线
建议按这个顺序继续:
QMainWindow(菜单栏、工具栏、状态栏)
QTableWidget / QTreeWidget
- 文件读写(JSON / SQLite)
QThread(耗时任务不卡 UI)
- 打包发布(PyInstaller)
11. 打包成可执行文件
1 2
| pip install pyinstaller pyinstaller -F -w main.py
|
-F:打成单文件
-w:Windows 下关闭控制台窗口
12. 总结
你现在已经掌握 PyQt6 的核心主线:
- 控件(Widget)
- 布局(Layout)
- 事件(Signal/Slot)
- 业务组织(分层拆分)
接下来建议直接做一个“可保存数据”的小项目,比如记账、任务管理、下载器,这样成长最快。