Qt 信号和槽
信号和槽(Signals and Slots)是Qt框架中的核心机制之一,用于对象之间的通信。它们提供了一种非常灵活和类型安全的事件处理系统,允许对象之间在发生特定事件时进行交互,而不需要紧密耦合。这使得代码更易于维护和扩展。
1.基本概念
信号(Signal)
- 信号是Qt对象在某些事件发生时自动发出的通知。
- 常用于表示对象的某种状态改变(如按钮点击、文本框内容改变)。
槽(Slot)
- 槽是一个普通的成员函数,用于处理信号。
- 槽可以有参数,参数类型和数量通常与信号匹配。
连接信号和槽(Connect)
- 使用
QObject
类的connect()
函数将信号和槽连接起来。 - 当信号发出时,相关的槽函数被调用。
2. 基本语法
定义信号和槽
定义信号:
signals:void signalName(); // 无参数信号void signalName(int value); // 带参数信号
定义槽:
public slots:void slotName(); // 无参数槽void slotName(int value); // 带参数槽
3. 信号和槽的特点:
- 松散耦合:信号和槽机制使得对象之间的依赖性降低。发送信号的对象不需要知道接收信号的对象是谁。
- 类型安全:在编译时检查信号和槽的参数匹配,这减少了运行时错误的可能性。
- 多对多通信:一个信号可以连接多个槽,一个槽也可以连接多个信号。这种机制非常灵活。
- 自定义信号和槽:开发者可以定义自己的信号和槽,以满足特定的需求。
4. 自己学习的时候遇到的坑小总结(这部分可能会持续更新):
4.1 信号可以传递信号
- 两个槽函数的声明:
private slots:void onNumChanged(int value);void onSpinBoxValueChanged(int value);
- 这是我定义的两个槽函数:
void Widget::onNumChanged(int value)
{qDebug("onNumChanged");ui->progressBar->setValue(value);
}void Widget::onSpinBoxValueChanged(int value)
{qDebug("onSpinBoxValueChanged");emit numChanged(value);
}
- 信号(只需要signals声明)
signals:void numChanged(int value);
- connect函数连接:
connect(ui->spinBox, SIGNAL(valueChanged(int)), this, SLOT(onSpinBoxValueChanged(int)));connect(this, SIGNAL(numChanged(int)), this, SLOT(onNumChanged(int)));
这部分是spinBox发出信号,接收者当前窗口,槽函数是onSpinBoxValueChanged
然后当前窗口再发送信号,接收者是当前窗口,槽函数是onNumChanged
这部分主要是实验一下自定义槽函数和信号,而不是直接使用valueChanged
- 重点: 除了中间用onSpinBoxValueChanged(int)这个槽函数来实现以外,可以直接在第一行槽函数的位置改成信号,用信号传递信号:
connect(ui->spinBox, SIGNAL(valueChanged(int)), this, SIGNAL(numChanged(int)));
connect(this, SIGNAL(numChanged(int)), this, SLOT(onNumChanged(int)));
这两行代码的功能和上面是一样的!
4.2 信号使用 signals声明,不需要实现,是public
- 信号(只需要signals声明)
signals:void numChanged(int value);
4.3 槽public/protected/private slots声明,必须实现(重要)
如果头文件里声明了却没有实现,就会报如下错误:
- error: LNK2019: 无法解析的外部符号 “private: void __cdecl Widget::onSpinBoxValueChanged(int)” (?onSpinBoxValueChanged@Widget@@AEAAXH@Z),函数 “private: static void __cdecl Widget::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void * *)” (?qt_static_metacall@Widget@@CAXPEAVQObject@@W4Call@QMetaObject@@HPEAPEAX@Z) 中引用了该符号
解决办法就是:把不用的槽函数的声明删除掉或者注释掉