目的:
整理常见的Qt信号与槽的连接几种方式以及连接方式参数了解。
1.Qt4书写方式
connect(pushButton,SIGNAL(clicked(bool checked)),&a,SLOT(quit()));
2.标准格式
格式:connect(&sender,&CLASSA::signal,&receiver ,&CLASSB:: slot, Qt::连接方式);
3.Qt5 lambda表达
connect(m_mainScene,&NpMainScene :: sigFlipFinished,this,[=](布尔状态){}); connect(button,&QPushButton :: cliked,[this,new_data,new_page] {UpdateDatabase(new_data); OpenNewPage(new_page);关闭();});
参考网址:https://www.cnblogs.com/wanghui1234/p/8964968.html
**变化:**在Qt 4 connect函数中,还有一个重要的限制!在传参的情况下,slot函数的参数个数一定要小于等于信号函数的参数个数,并且要一一对应关系,可以小于,但是参数必须要对应关系。在Qt5的新版本中,connect函数添加了对lambda的支持-可以用lambda替代信号/插槽函数。自由地扩展其功能,并且可以忽略信号参数的影响,而且connect的形式也进一步精简了。
要注意connect(&sender,&CLASSA::signal,&receiver ,&CLASSB:: slot, Qt::连接方式); 对于函数重载类型容易报错。
自动关联
自动关联注意:
1: 设置object name
2:在对应的槽函数中命名为on_objectname_signal name
3: 在setupUi前调用(主要是因为connectSlotsByName())
连接参数
**AutoConnection(默认)**如果信号是在接收对象具有亲缘关系的线程中发出的,那么其行为与直接连接直接连接相同。否则,其行为与排队连接排队的连接相同。
** Direct Connection **当信号发出时,立即调用插槽。这个插槽是在发送方的线程中执行的,而不一定是接收方的线程。
QueuedConnection当控制返回到接收方线程的事件循环时调用插槽。插槽在接收线程中执行。
BlockingQueuedConnection插槽将与级联连接相同的串联连接方式被调用,但是当前线程中断,直到该插槽返回。注意使用此类型连接同一线程中的对象将导致死锁。
** Unique Connection **如果相同的信号已经连接到同一对象的同一插槽,则不进行连接,且connect()返回false。可与其他连接方式进行or操作
此方法不针对与lambda等行为的匿名函数。
note:
qInfo() << __FUNCTION__ << "second " << connect(ui->pushButton_3, &QPushButton::clicked, this, &MainWindow::testSlot, Qt::UniqueConnection);
qInfo() << __FUNCTION__ << "third " << connect(ui->pushButton_3, &QPushButton::clicked, this, &MainWindow::testSlot);
这种情况下connect不会返回false
扩展
当一个连接到槽函数的信号被发射时,槽函数将被调用。槽函数是普通的C++函数,在实际开发中也可以正常调用;它们唯一的特点是:【信号可以与它们相连接】。
由于槽是普通的成员函数,所以它们在直接调用时遵循普通的C++规则。但是,作为槽函数时,任何组件都可以通过信号连接从而调用它们。
还可以将槽函数定义为虚拟的,这在开发中非常有用。
与回调机制相比,信号和槽函数机制的速度稍微慢一些,这一点对于实际应用程序来说,这种差别并不显著。一般来说,发送一个连接到某些槽函数的信号,比直接调用非虚函数要慢大约10倍。这是定位连接对象、安全地遍历所有连接(即检查后续接收方在发射过程中没有被销毁)以及以函数调用增加的开销。虽然10个非虚函数调用听起来很多,但是它比new操作或delete操作的开销要小得多。一旦在后台执行一个需要new或delete的字符串、向量或列表操作,信号和槽函数的开销只占整个函数调用开销的很小一部分。在槽函数中执行系统调用时也是如此(或间接调用超过十个函数)。因此信号和槽函数机制的简单性和灵活性是值得的,这些开销在实际应用场景下甚至不会注意到。
注意,当与基于Qt的应用程序一起编译时,定义为信号或槽的变量的第三方库可能会导致编译器出现警告和错误。要解决这个问题,使用 #undef 来定义出错的预处理器符号即可。