QT-自定义信号槽与connect函数
本文最后更新于:1 年前
自定义信号函数
信号函数需要符合以下条件:
- 定义在某个类中,该类直接或间接继承自 QObject 类
- 用 signals 关键字修饰
- 函数只需要声明,不需要定义(实现)
- 函数的返回值类型为 void,参数的类型和个数不限
对于 Qt 提供的信号函数,其底层已经设置好了信号发出的时机,例如按下鼠标时、点击 Enter 回车键时等等。
对于自定义的信号,需要自行指定信号发出的时机,这就需要用到 emit 关键字。emit 是 Qt 在 C++ 基础上扩展的一个关键字,专门用来发射信号。
1 |
|
自定义槽函数
槽函数需要符合以下条件:
槽函数既可以是普通的全局函数、也可以是类的成员函数、静态成员函数、友元函数、虚函数,还可以用 lambda 表达式表示
Qt4 中的槽函数只能是 slots 修饰的类成员函数,Qt5 中取消了这一限制
槽函数的返回值必须和信号函数相同,由于信号函数的返回值一定是 void,所以槽函数的返回值也必须为 void
对于带参的信号函数,槽函数可以选择接收所有参数,但参数的类型、顺序、个数都必须与信号函数相同;也可以选择接收前几个参数,这些参数的类型、顺序都必须与信号函数相同;还可以选择不接受任何参数
槽函数的参数不能有默认值
下面的例子展示了响应 MySignal 信号的自定义槽函数:
1 |
|
程序中,重点关注 recSlot1()、recSlot2()、recSlot3() 这 3 个函数:
recSlot1() 是 MyWidget 类内部的 public 成员函数,可以当做槽函数使用;
QObject::connect(&mywidget,&MyWidget::MySignal,&mywidget,&MyWidget::recSlot1);
recSlot2() 位于 MyWidget 类的内部,修饰它的关键字是 public slots。slots 和 emit 一样,是 Qt 扩展的一个关键字,专门用来修饰槽函数。也就是说,recSlot2() 是 MyWidget 类中的槽函数。
QObject::connect(&mywidget,&MyWidget::MySignal,&mywidget,&MyWidget::recSlot2);
recSlot3() 是全局函数,可以当做槽函数使用
QObject::connect(&mywidget,&MyWidget::MySignal,&recSlot3);
connect函数
用法一:使用SIGNAL和SLOT宏
connect函数用来连接信号和槽函数,在 Qt5 版本之前,其最常用的语法格式是:
QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)
各个参数的含义分别是:
- sender:指定信号的发送者;
- signal:指定信号函数,信号函数必须用 SIGNAL() 宏括起来;
- reveiver:指定信号的接收者;
- method:指定接收信号的槽函数,槽函数必须用 SLOT() 宏括起来;
- type: 用于指定关联方式,默认的关联方式为 Qt::AutoConnection,通常不需要手动设定。
用法二:使用&类名::函数名
Qt5 版本中,不再使用 SIGNAL() 和 SLOT() 宏,实现代码为:
connect(&But, &QPushButton::clicked, &widget, &QWidget::close);
可以看到,新版 connect() 函数指定信号函数和槽函数的语法格式是 &+函数所在类+函数名
用法三:Lambda表达式
在Pro项目文件中加入 CONFIG += C++ 11后,可以在connect函数中使用Lambda表达式,直接编写信号发射后要执行的代码,不需要定义槽函数。
1 |
|
connect在只有三个参数的情况下,默认第三个槽函数的对象是本类this,也就是第三个参数this被省略了。
用法四:省略connect函数,自动连接信号和槽
Qt信号和槽函数的命名是有规则的,组成为 on_对象名_信号
,就可以省略connect而直接实现信号和槽的连接。以按钮为例:
void on_pushButton_clicked();
此外,一个 connect() 函数只能关联一个信号函数和一个槽函数,但程序中可以包含多个 connect() 函数,用于实现以下几种效果:
- 关联多个信号函数和多个槽函数;
- 一个信号函数可以关联多个槽函数,当信号发出时,与之关联的槽函数会一个接一个地执行,但它们执行的顺序是随机的,无法人为指定哪个先执行、哪个后执行;
- 多个信号函数可以关联同一个槽函数,无论哪个信号发出,槽函数都会执行。