qt入门tutorial-第二节
2025年4月21日大约 2 分钟
如何确定某个函数是signal还是slot
对于信号(Signal):
声明方式:在类声明中使用
signals:
区域声明signals: void valueChanged(int newValue); void operationCompleted();
特点:
- 只有声明,没有实现代码(由moc自动生成)
- 返回类型必须是void
- 可以带参数但不能有默认参数
- 信号总是protected权限(只能在类内emit)
调用方式:使用
emit
关键字触发emit valueChanged(10);
对于槽(Slot):
- 声明方式:在类声明中使用
public slots:
或private slots:
等区域声明public slots: void setValue(int value); void doCalculation();
- 特点:
- 需要完整的实现(像普通成员函数一样)
- 可以是虚函数
- 可以有各种返回类型和参数
- 可以设置访问权限(public/protected/private)
- Qt5新特性:任何函数都可以作为槽,不一定要声明在slots区域
识别方法总结:
- 查看类声明中的
signals:
和slots:
区域 - 在Qt Creator中,信号会有特殊图标(闪电符号)
- 信号只能声明不能实现,槽必须有实现
- 文档中会明确标注(Qt Assistant中的信号/槽标记)
连接信号与槽的其他方式
除了使用QObject::connect()
,还有以下几种方式:
(1) Qt5的新连接语法(C++11)
// 传统方式
connect(sender, SIGNAL(valueChanged(int)), receiver, SLOT(setValue(int)));
// Qt5新语法 - 编译时检查
connect(sender, &SenderClass::valueChanged, receiver, &ReceiverClass::setValue);
// 使用lambda表达式
connect(sender, &SenderClass::valueChanged, [=](int value) {
receiver->doSomething(value);
});
(2) 自动连接(UI文件)
- 在Qt Designer中命名对象和槽函数遵循特定模式
- 使用
QMetaObject::connectSlotsByName()
自动连接 - 命名规则:
on_<发送者对象名>_<信号名>
// 自动连接的槽函数声明 private slots: void on_pushButton_clicked();
(3) 通过QML连接
- 在QML中可以直接使用JavaScript语法连接信号与槽
Button { onClicked: { handler.handleClick() } }
(4) 直接调用
- 虽然不推荐,但可以直接在信号触发的地方调用槽函数
emit valueChanged(10); // 触发信号 receiver->setValue(10); // 直接调用槽
(5) 使用事件过滤器
- 虽然不是直接的信号槽连接,但可以用于对象间通信
- 通过
installEventFilter()
和eventFilter()
实现
最佳实践建议:
- 优先使用Qt5的新连接语法(编译时类型检查)
- 简单的UI操作可以使用自动连接
- 复杂的逻辑关系使用显式connect
- 避免混合使用多种连接方式造成混乱
这些方法各有适用场景,QObject::connect()
仍然是最灵活和强大的核心连接机制。