QT信号与槽的机制简析

如果你是一个QT开发者或者曾使用过QT编写你的程序,那么你应该知道QT特有的信号与槽的机制,作为QT的核心功能,这是每一个QT开发者都必须熟练掌握的知识。

QT提供的信号和槽的机制多用于界面操作的响应,完成两个QT对象之间的通信,其基本原理就是在链接信号与槽之后,在某个需要的时候发送信号,槽接收到这个信号并对信号进行处理,这种触发机制是跨类、线程的,一般主线程的UI变化都是通过信号与槽进行更新。众所周知,目前大多数包括UI界面的语言和平台,其UI线程都是相对独立的,其他类并不可以直接更新UI内容,且UI所在线程不可阻塞。此时我们就通过信号告知UI线程中的槽完成相对应的操作。

信号与槽机制的特点

  • 可继承:信号与槽是可以被继承的,当一个类被继承之后,该类的信号与槽也同时会被继承;
  • 类型安全:只有参数匹配的信号与槽才可以连接成功(信号的参数可以更多,槽会忽略多余的参数)。
  • 线程安全:通过借助QT自已的事件机制,信号槽支持跨线程并且可以保证线程安全。
  • 松耦合:信号不关心有哪些或者多少个对象与之连接;槽不关心自己连接了哪些对象的哪些信号。这些都不会影响何时发出信号或者信号如何处理。
  • 信号与槽是多对多的关系:信号与槽的链接是没有限制的,一个信号可以连接多个槽,一个槽也可以用来接收多个信号,甚至我们可以用一个信号连接另一个信号,虽然这并没有什么意义。

信号与槽的使用流程:

  1. 对象A定义信号(signal),这个信号可以是一个UI控件,也可以是自定义信号;
  2. 对象B定义一个槽函数,用于接收信息;
  3. 使用connect(object1,SIGNAL(signal),Object2,SLOT()); 函数连接信号与槽;
  4. 使用emit 发送指定的信号,或者通过其他方式出发signal;
  5. 当信号发射后,槽会就接收到响应。

示例:

MainWindow::MainWindow(QWidget *parent) :
     QMainWindow(parent),
     ui(new Ui::MainWindow)
 {
     connect(this,SIGNAL(signal1()),this,SLOT(_onsignal1()));//连接信号与槽函数
     emit signal1();//发射信号
     qDebug()<<"001";
 }
 void MainWindow::_onsignal1()
 {
     sleep(2);
     qDebug()<<"002";
 }

运行上段代码我们发现,不论我们如何等待,函数总是等待处理完发射的信号之后才会继续执行emit之后的代码,如果槽函数是一个无限循环,那么ui界面将卡死,这说明在默认的情况下,在单线程中函数在执行emit发射一个信号之后,会立刻跳转到槽函数处理这个信号,当槽函数执行完毕之后,emit关键字之后的函数才会继续运行。跳转到connect函数的定义我们发现,我们所使用的槽函数实际上有五个参数,一般我们只使用4个参数连接,第五个参数实际上是一个连接类型,分别是:AutoConnection,DirectConnection,QueuedConnection,BlockingQueuedConnection。通过传入不同的连接类型,将使用不同的连接方式,默认使用AutoConnection,即上述代码中的连接机制,直接调用slot。

不同的连接类型解析:

  • QueuedConnection:此机制是当信号产生时间,信号会暂时被缓冲到一个消息队列中,等待接收者的事件循环处理去队列中获取消息,然后执行和信号关联的槽函数,这种方式既可以在同一线程内传递消息也可以跨线程操作。
  • BlockingQueuedConnection:处理方式和QueuedConnection相同,但是它只能应用于跨线程操作即发送者和接收者处于不同的线程中的情况,并且信号发送者线程会阻塞等待接收者的槽函数执行结束。
  • DirectConnection:信号一旦发射,立刻调用与之关联的槽函数,这种类型无法支持跨线程的通信。
  • AutoConnection:当信号发送者和接收者处于同一线程内时,这个类型等同于DirectConnection,反之等同于QueuedConnection,这个类型也是connect函数的默认连接类型。

 

以上为QT信号与槽的机制的相关内容,如果你有更好的理解或更多的内容,请评论或邮件联系我。

发表评论