最近在做一个简单的桌宠,以下记录我对C++ Qt的一些理解。

我认为,一个Qt应用主要围绕两大块:同步的UI初始化异步的事件循环

1. 同步的UI初始化

Qt 窗口(或任何 QWidget)的生命周期始于其构造函数。在这里,我们以常规的、同步的方式完成所有UI布局和初始属性设置。这部分代码会一次性执行完毕,构建出窗口的静态初始外观。用时可以忽略不计。

需要延时触发/用户事件驱动的部分就需要Qt特别的事件处理机制————信号与槽来实现。

2. 异步的事件循环

静态的UI只有在响应外部变化(如用户点击、网络数据到达、定时器触发)时才具有生命力。Qt 通过一个持续运行的事件循环 (Event Loop) 来管理这一切。

程序在完成同步初始化后,会交出控制权给事件循环。事件循环负责监听各种事件源,并将它们派发给相应的对象。而信号与槽 (Signals & Slots) 机制,正是 Qt 对这种异步模型优雅、类型安全的封装。

信号Signal:当某个对象的状态发生改变(如 QPushButton 被点击),它会 emit 一个信号。信号本身不关心谁会接收它。

槽Slot:一个普通的成员函数,用于响应信号。当它与一个信号 connect 后,一旦信号发出,这个槽函数就会被事件循环调度执行。

默认情况下:信号与槽是“同步的”。

整个流程是:事件发生 → 对象发射信号 → 事件循环 → 调度已连接的槽函数执行

2.1. 定时触发

QTimer是Qt提供的一个定时器类,在其线程的事件循环中定期投递 timeout 事件,随后触发信号。

它是体现事件驱动的绝佳例子。

它不在当前代码流里“等待”,而是向事件循环注册一个未来的任务。

可以利用QTimer以及timeout信号来实现定时触发事件。

以下代码并不会阻塞,start() 只是告诉事件循环“请每隔1000毫秒,帮我把 timertimeout 信号发出来”。

1
2
3
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &MyClass::onTimeout);
timer->start(1000); // 非阻塞,立即返回

2.2. 单次延时触发

QTimer::singleShot 是一个更便捷的静态函数,它请求事件循环“在1000毫秒后,帮我执行一次这个 Lambda 函数”。这对于实现“稍后执行”的逻辑非常有用。

1
2
3
QTimer::singleShot(1000, this, [this](){
// 这部分代码将在 1 秒后由事件循环调用
});

通过这种方式,复杂的异步逻辑被分解为一系列由事件驱动的、简短的槽函数调用,避免了回调地狱,也让代码结构保持清晰。

之后遇到了需要QThread的时候再介绍Qt的线程~