文章目录
QT信号与槽机制详解
QT的信号与槽机制是其核心特性之一,提供了一种强大的对象间通信方式,比传统的回调函数更加灵活和安全。
基本概念
信号(Signal)
- 信号是QT中由
QObject
派生类可以发出的通知 - 信号只有声明没有实现,由
moc
(元对象编译器)自动生成 - 信号可以带有任意数量和类型的参数
- 信号使用
emit
关键字触发
槽(Slot)
- 槽是普通的C++成员函数,可以被正常调用
- 槽可以连接到信号,当信号发出时自动调用
- 槽可以有参数,但参数类型必须与连接的信号兼容
- 槽可以有返回值,但通常被忽略(因为信号没有返回值)
信号与槽的连接方式
基本语法
QObject::connect(
sender, // 发送对象指针
SIGNAL(signalSignature), // 信号签名
receiver, // 接收对象指针
SLOT(slotSignature) // 槽签名
);
QT5新语法(推荐)
QObject::connect(
sender, // 发送对象指针
&SenderClass::signalName, // 信号成员函数指针
receiver, // 接收对象指针
&ReceiverClass::slotName // 槽成员函数指针
);
信号与槽的特点
- 类型安全:参数类型必须匹配,编译时检查(QT5语法)
- 松耦合:发送者不知道接收者信息
- 多对多:一个信号可以连接多个槽,一个槽可以接收多个信号
- 线程安全:支持跨线程通信
- 自动断开:当对象被删除时,连接自动断开
实际示例
传统方式
// 定义包含信号和槽的类
class MyClass : public QObject {
Q_OBJECT
public:
explicit MyClass(QObject *parent = nullptr);
signals:
void valueChanged(int newValue);
public slots:
void setValue(int value);
};
// 连接信号与槽
MyClass obj1, obj2;
QObject::connect(&obj1, SIGNAL(valueChanged(int)), &obj2, SLOT(setValue(int)));
// 触发信号
obj1.valueChanged(42); // 这将调用obj2.setValue(42)
QT5新语法
// 连接
QObject::connect(&obj1, &MyClass::valueChanged, &obj2, &MyClass::setValue);
// 也可以使用lambda表达式
QObject::connect(&obj1, &MyClass::valueChanged, [](int value) {
qDebug() << "Value changed to:" << value;
});
连接类型
QT提供了不同的连接类型:
Qt::AutoConnection // 默认(同线程直接连接,跨线程队列连接)
Qt::DirectConnection // 直接调用,在发送者线程执行
Qt::QueuedConnection // 异步,在接收者线程执行
Qt::BlockingQueuedConnection // 同步,在接收者线程执行并阻塞发送者线程
Qt::UniqueConnection // 唯一连接,防止重复连接
注意事项
- 使用信号和槽的类必须在类声明中包含
Q_OBJECT
宏 - 信号和槽的参数类型必须是QT元对象系统认识的类型,或使用
qRegisterMetaType()
注册 - 槽函数可以有默认参数,但信号不能有
- 信号与槽的效率比直接函数调用稍低,但提供了更大的灵活性
高级用法
信号连接信号
// 当signal1发出时,自动触发signal2
connect(obj1, &Class1::signal1, obj2, &Class2::signal2);
使用lambda表达式
connect(button, &QPushButton::clicked, [=]() {
// 处理点击事件
});
自动断开连接(QT5)
// 当接收者被删除时自动断开
connect(sender, &Sender::signal, receiver, &Receiver::slot, Qt::UniqueConnection);
自动断开连接(QT5)
// 当接收者被删除时自动断开
connect(sender, &Sender::signal, receiver, &Receiver::slot, Qt::UniqueConnection);
信号与槽机制是QT框架中最强大和独特的特性之一,它极大地简化了对象间的通信,特别是在GUI编程中处理用户交互事件时。