3、PyQt5 基础与第一个窗口

好,咱们正式开始动手了。

上一章我们把开发环境搭好了,Python 能跑,PyQt5 也装上了。现在,是时候写第一个窗口了。

说实话,我当年第一次接触 PyQt5 时,看着那一堆类和方法,心里也犯嘀咕。但后来发现,核心概念就那么几个。搞懂了,后面就顺了。

3.1 PyQt5 核心概念:信号与槽、事件循环

先聊两个最基础的概念。不理解它们,后面写代码会懵。

3.1.1 信号与槽

说白了,这就是 PyQt5 里对象之间通信的方式。

你想想看,你点了一个按钮,程序怎么知道该执行哪段代码?

在 PyQt5 里,按钮被点击时会发射一个信号(Signal)。你需要把这个信号连接到一个槽(Slot)上。槽,就是一个函数。信号发射了,槽函数就会被自动调用。

核心理解:

  • 信号(Signal):事件发生时发出的通知。比如按钮被点击、滑块被拖动、窗口被关闭。
  • 槽(Slot):响应信号的函数。可以是 PyQt5 内置的,也可以是你自己写的。
  • 连接(Connect):把信号和槽绑定在一起。

我在项目中遇到过一个问题:多个按钮需要执行类似的操作。如果每个按钮都写一个槽函数,代码会非常冗余。后来我学会了用同一个槽函数,通过 sender() 方法判断是哪个按钮触发的。嗯,这个技巧后面会讲。

# 最简单的信号与槽示例
button.clicked.connect(self.on_button_clicked)

def on_button_clicked(self):
    print("按钮被点击了!")

3.1.2 事件循环

这个更关键。

你写一个普通的 Python 脚本,跑完就结束了。但 GUI 程序不能这样。它得一直等着,等用户点击、等键盘输入、等窗口重绘。

事件循环(Event Loop)就是干这个的。它像一个永不停止的 while 循环,不断监听各种事件,然后分发给对应的处理函数。

我的理解:

事件循环就是 GUI 程序的心脏。它一直在跳,程序才能活着。你调用 app.exec_() 时,事件循环就启动了。程序会一直运行,直到你关闭窗口。

为什么会这样?因为 PyQt5 把底层的消息循环封装好了。你不需要自己写 while 循环,只需要调用 app.exec_() 就行。

3.2 创建第一个主窗口(QMainWindow)

好,概念讲完了。咱们写代码。

我个人习惯,每次新建项目都会先创建一个主窗口。QMainWindow 是 PyQt5 里最常用的窗口类。它自带菜单栏、工具栏、状态栏,非常方便。

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        # 设置窗口标题
        self.setWindowTitle("我的第一个地面站")
        # 设置窗口图标(需要先导入 QIcon)
        # self.setWindowIcon(QIcon('icon.png'))
        # 设置窗口大小
        self.resize(800, 600)
        # 设置窗口位置(屏幕左上角为原点)
        self.move(300, 200)

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

这段代码,你直接复制到 Python 文件里运行,就能看到一个窗口了。

注意:

如果你用的是 PyQt5 的某些版本,设置图标时可能会遇到路径问题。我曾经因为图标路径写错了,折腾了半小时。建议先用注释掉图标设置,等窗口跑起来再慢慢调。

3.3 设置窗口标题、图标、大小与位置

上面代码里已经用到了几个方法。我再详细说说。

方法 作用 示例
setWindowTitle() 设置窗口标题 setWindowTitle("无人机地面站")
setWindowIcon() 设置窗口图标 setWindowIcon(QIcon('logo.png'))
resize() 设置窗口大小(宽,高) resize(1024, 768)
move() 设置窗口位置(x, y) move(100, 100)
setGeometry() 同时设置位置和大小 setGeometry(100, 100, 1024, 768)

我个人习惯用 setGeometry(),一行代码搞定位置和大小。但要注意,它的参数顺序是 (x, y, width, height),别搞反了。

3.4 理解 QApplication 与 QWidget 的关系

这是很多人容易混淆的地方。

QApplication 是整个应用程序的管理者。它负责初始化、事件循环、全局设置。每个 PyQt5 程序有且只有一个 QApplication 实例。

QWidget 是所有窗口和控件的基类。QMainWindow 继承自 QWidget。你看到的按钮、标签、输入框,都是 QWidget 的子类。

关系总结:

  • QApplication 是「老板」,管理整个程序的生命周期。
  • QWidget 是「员工」,负责具体的界面展示和交互。
  • 一个 QApplication 可以管理多个 QWidget。

你想想看,如果没有 QApplication,你的窗口就没人管。事件循环跑不起来,窗口显示一下就退出了。

我曾经犯过一个低级错误:在创建 QApplication 之前就创建了窗口。结果程序直接崩溃。嗯,顺序很重要。

3.5 本章知识体系

下面这张图,是我画的核心逻辑。你看一眼,应该就能把本章内容串起来。

PyQt5 基础与第一个窗口 - 知识体系 QApplication 事件循环 (exec_()) QMainWindow QWidget (基类) 信号与槽 核心关系:QApplication 管理事件循环,事件循环驱动 QWidget 及其子类,信号与槽实现组件间通信

我的建议:

刚开始学,不要纠结于所有细节。先把 QApplication 和 QMainWindow 的关系搞清楚。能跑起来一个窗口,你就成功了一半。

后面的章节,我们会在这个窗口里添加各种控件。到时候,信号与槽会频繁用到。现在有个印象就行。

好了,这一章的内容就这些。代码不多,但概念很重要。你最好亲手敲一遍,跑起来看看效果。


可可精品资料库