PyQt5基础:从安装到第一个窗口程序

各位同学,今天我们来聊聊PyQt5。说实话,这个库是我做上位机开发时用得最多的工具之一。记得我第一次接触它,是在一个工业镜头测试项目里——甲方要求三天出原型,我硬是用PyQt5两天就搞定了。嗯,今天就把这些经验分享给你们。

1. PyQt5的安装

安装其实很简单,但有个坑我得先提醒你:Python版本和PyQt5版本要匹配。我曾经在Python 3.12上直接pip install PyQt5,结果报了一堆错——后来发现是版本兼容问题。

我个人习惯用Python 3.8到3.10之间的版本,稳定。安装命令就一行:

pip install PyQt5 pyqt5-tools

这里我建议加上pyqt5-tools,因为它包含了Qt Designer——我们后面会用到。装完之后,验证一下:

python -c "from PyQt5.QtWidgets import QApplication; print('OK')"

如果打印出"OK",恭喜你,环境搭好了。

小提示: 如果你在macOS上安装,可能会遇到权限问题。加个--user参数就行:pip install --user PyQt5

2. Qt Designer:可视化设计利器

Qt Designer是什么?说白了,就是一个拖拽式的界面设计工具。你想想看,如果每个按钮、每个文本框都要手写代码去布局,那得多累?

启动它很简单:在命令行输入designer,或者找到安装目录下的designer.exe。界面长这样:

  • 左侧是控件面板——按钮、标签、输入框都在这里
  • 中间是设计区域——你的窗口画布
  • 右侧是属性编辑器——调整控件的大小、颜色、文字

我在项目中常用的流程是:先用Qt Designer拖出界面,保存为.ui文件,然后用pyuic5工具转成Python代码。命令如下:

pyuic5 -x my_design.ui -o my_design.py

这样生成的代码可以直接运行。但说实话,我更喜欢另一种方式——动态加载UI文件,这样修改界面时不用重新生成代码:

from PyQt5 import uic
from PyQt5.QtWidgets import QApplication

app = QApplication([])
window = uic.loadUi('my_design.ui')
window.show()
app.exec_()
核心要点: Qt Designer生成的UI文件本质是XML格式。你可以用文本编辑器打开看看,里面描述了每个控件的位置、大小、属性。理解这一点,后面调试布局问题会轻松很多。

3. 信号与槽机制:PyQt5的灵魂

信号与槽,这个词听起来有点玄乎。其实说白了就是:某个事件发生了,就触发某个函数去处理

举个例子:你点击一个"拍照"按钮,程序就要去调用相机。这里的"点击"就是信号,"调用相机"就是槽函数。

我刚开始学的时候,总觉得这个概念抽象。直到有一次做项目,我需要让一个滑动条控制镜头的光圈值——滑动条的值变了,光圈数值显示也要跟着变。这就是典型的信号与槽:

from PyQt5.QtWidgets import QSlider, QLabel

# 创建控件
slider = QSlider()
label = QLabel('光圈值: 2.8')

# 连接信号与槽
slider.valueChanged.connect(lambda v: label.setText(f'光圈值: {v/10:.1f}'))

这里valueChanged就是信号,connect方法把信号和槽函数绑在一起。每当滑动条的值变化,标签的文字就会更新。

注意: 信号与槽的连接,参数类型必须匹配。比如valueChanged信号会传递一个整数,你的槽函数就必须能接收整数参数。我曾经在这里栽过跟头——传了个字符串进去,程序直接崩溃。

PyQt5内置了很多信号,比如:

控件 信号 触发时机
QPushButton clicked 按钮被点击
QLineEdit textChanged 文本内容变化
QComboBox currentIndexChanged 下拉选项改变
QSlider valueChanged 滑块位置变化

你还可以自定义信号。比如在镜头测试中,当图像采集完成时,我习惯发射一个自定义信号:

from PyQt5.QtCore import pyqtSignal, QObject

class CameraController(QObject):
    image_captured = pyqtSignal(str)  # 自定义信号,传递图片路径

    def capture(self):
        # 采集图像...
        self.image_captured.emit('/path/to/image.jpg')

4. 第一个窗口程序

好了,理论说完了,我们来写第一个程序。这个程序很简单:一个窗口,上面有个按钮,点击按钮就显示"Hello, 镜头测试系统!"

完整代码如下:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QVBoxLayout

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
    
    def initUI(self):
        # 创建控件
        self.label = QLabel('等待点击...')
        self.button = QPushButton('点击我')
        
        # 连接信号与槽
        self.button.clicked.connect(self.on_button_clicked)
        
        # 布局
        layout = QVBoxLayout()
        layout.addWidget(self.label)
        layout.addWidget(self.button)
        self.setLayout(layout)
        
        # 窗口设置
        self.setWindowTitle('第一个PyQt5程序')
        self.resize(300, 200)
    
    def on_button_clicked(self):
        self.label.setText('Hello, 镜头测试系统!')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

运行这段代码,你会看到一个300x200的窗口。点击按钮,标签文字就会变化。嗯,就是这么简单。

我的习惯: 每次新建项目,我都会先跑通这样一个最小程序。它能验证环境、验证信号与槽、验证布局——相当于给整个项目打个地基。

这里有个细节要注意:QApplication必须在使用任何Qt控件之前创建。它管理着整个应用程序的资源,包括事件循环、剪贴板、字体设置等。如果你忘了这行,程序会直接报错。

知识体系总览

为了让你更直观地理解本章内容,我画了一张图:

PyQt5基础知识体系 安装配置 pip install PyQt5 pyqt5-tools 版本兼容检查 Qt Designer 拖拽式界面设计 .ui文件生成 pyuic5转换 信号与槽 事件驱动机制 connect连接 自定义信号 第一个窗口程序 QWidget + QPushButton + 信号与槽 三个模块环环相扣:安装是基础,Designer提效率,信号与槽是核心 最终汇聚到第一个可运行的窗口程序

这张图把本章的三个核心内容串起来了。你想想看,安装是基础,Qt Designer帮你快速搭界面,信号与槽让界面"活"起来——三者缺一不可。

好了,今天的分享就到这里。记住:动手写代码比看十遍教程都管用。打开你的编辑器,把那个第一个窗口程序跑起来,然后试着改改按钮的文字、换个信号试试。遇到问题很正常,我当年也是这么过来的。