QT对信号与槽的理解

本文深入探讨了Qt的信号与槽机制,它是Qt框架的核心功能,提供了一种类型安全的对象间通信方式。信号在对象状态变化时发出,槽则作为响应函数。信号和槽可以有任意参数,且类型安全,允许多对多的连接。Qt提供了多种连接方式,包括通过编辑器、代码手动连接以及利用命名规则自动连接。此外,信号和槽可以使用默认参数,支持异步和同步执行,并能与其他信号/槽系统(如Boost)共存。
摘要由CSDN通过智能技术生成

文章目录
01. 信号与槽
2. 介绍
3. 信号与槽
4. 信号
5. 槽
6. 信号与槽的四种实现方式
7.示例
8. 实例
9. 信号和槽使用默认参数
10. 信号与槽高级用法
11. 使用Qt与第三方信号和插槽
12. 深入理解信号与槽

01. 信号与槽
​ 信号和槽用于对象之间的通信。信号和插槽机制是Qt的核心功能,可能是与其他框架提供的功能最不同的部分。Qt的元对象系统使信号和槽成为可能。
02. 介绍
​ 在GUI编程中,当我们更改一个小部件时,我们经常需要通知另一个小部件。更一般地说,我们希望任何类型的对象能够彼此通信。例如,如果用户单击“ **关闭”**按钮,我们可能希望调用窗口的close()函数。
​ 其它工具包使用回调实现这种通信。回调是指向函数的指针,因此如果您希望处理函数通知您某些事件,则将指针传递给处理函数的另一个函数(回调)。然后,处理函数在适当时调用回调。虽然确实存在使用此方法的成功框架,但回调可能不直观,并且可能在确保回调参数的类型正确性方面存在问题。
03. 信号与槽
​ 在Qt中,我们有一种替代回调技术:我们使用信号和槽。发生特定事件时会发出信号。Qt的小部件有许多预定义信号,但我们总是可以将部件子类化为了向它们添加我们自己的信号。槽是响应于特定信号而被调用的函数。Qt的部件中有许多预定义的槽函数,但通常的做法是将部件子类化并添加自己的槽,以便您可以处理您感兴趣的信号。

​ 信号和槽机制是类型安全的:信号的签名必须与接收槽的签名匹配。(事实上,一个槽可能比它收到的信号具有更短的签名,因为它可以忽略额外的参数。)由于签名是兼容的,编译器可以帮助我们在使用基于函数指针的语法时检测类型不匹配。基于字符串的SIGNAL和SLOT语法将在运行时检测类型不匹配。信号和槽是松散耦合:发出信号的类既不知道也不用关心哪个槽接收该信号。Qt的信号和槽机制确保如果您将信号连接到槽,将在适当的时间使用信号的参数调用槽。信号和槽可以采用任何类型的任意数量的参数。它们完全是类型安全的。
​ 从QObject或其子类之一(例如,QWidget)继承的所有类都可以包含信号和槽。当它们以某种方式改变它的状态时, 信号就会被发送, 其它对象可能对该信号感兴趣。这是的话所有的对象都可以通讯。它不知道或关心是否有任何东西正在接收它发出的信号。这是真正的信息封装,并确保该对象可以用作软件组件。
​ 槽可用于接收信号,但它们也是普通的成员函数。就像一个对象不知道是否有任何东西接收到它的信号一样,一个槽函数不知道它是否有任何信号连接到它。这确保了可以使用Qt创建真正独立的组件。
​ 可以将任意数量的信号连接到一个槽,并且可以根据需要将信号连接到任意数量的插。甚至可以将信号直接连接到另一个信号。(每当发射第一个信号时,将立即发出第二个信号。)
信号和插共同构成了一个强大的组件编程机制。
04. 信号
​ 当对象的内部状态以某种可能对对象的客户端或所有者感兴趣的方式发生更改时,对象会发出信号。信号是公共访问函数,可以从任何地方发出,但我们建议只从定义信号及其子类的类中发出它们。
​ 当信号发出时,通常会立即执行与其连接的槽函数,就像正常的函数调用一样。发生这种情况时,信号和槽机制完全独立于任何GUI事件循环。emit发出信号之后, 所有与它关联的槽函数将会被执行。这种情形与使用排队连接时情况略有不同; 在这种情况下,emit关键字后面的代码将立即继续,并且稍后将执行槽函数。
​ 如果多个槽连接到一个信号,则在发出信号时,槽函数将按照它们已连接的顺序依次执行。
​ 信号由moc自动生成,不得在.cpp文件中实现。它们永远不会有返回类型(即使用void)。
关于参数的说明
我们的经验表明,如果信号和槽不使用特殊类型,则它们可以重复使用。如果QScrollBar :: valueChanged()使用特殊类型,例如假设的QScrollBar :: Range,则它只能连接到专门为QScrollBar设计的槽函数。将不同的输入控件连接在一起是不可能的。
05. 槽
​ 当连接的信号被发送时, 对应的槽函数将会被执行。槽函数是普通的C ++函数,可以正常调用; 它们唯一的特点是信号可以连接到它们。
​ 由于插槽是普通的成员函数,因此它们在直接调用时遵循正常的C ++规则。但是,作为槽,它们可以通过信号和槽连接由任何组件调用,而不管其访问级别如何。这意味着从任意类的实例发出的信号可以导致在不相关的类的实例中调用私有槽。
​ 我们发现这些槽在实践中非常有用时, 还可以将槽函数定义为虚槽函数。
​ 与回调相比,信号和槽稍微慢一些,因为它们提供了更大的灵活性,尽管实际应用的差异是微不足道的。通常,发射连接到某些槽的信号比使用非虚函数直接调用槽函数大约慢十倍。这是定位连接对象,安全地遍历所有连接(即检查后续槽函数在发射期间没有被销毁)以及以通用方式编组任何参数所需的开销。虽然十个非虚函数调用可能听起来很多,但它的开销比任何new或delete操作都少得多,例如。只要执行场景后面的字符串,vector或list操作,就需要new或delete,信号和槽开销仅仅是函数调用开销的一小部分。无论何时在槽函数中进行系统调用,情况都是如此; 或间接调用十多个函数。由于信号和槽机制的简单性和灵活性, 这一点开销是非常值得的,用户甚至都不会注意到。
​ 请注意,定义变量的其他库在与基于Qt的应用程序一起编译时调用signals或slots可能导致编译器警告和错误。要解决这个问题,#undef违规的预处理器符号。
06. 信号与槽的四种实现方式
(1)、以按钮为例,首先添加一个按钮,对象名为pushButton,在按钮是右键单击选择“转到槽”即可,在转到槽选择面板(右图)里面选择需要进行的操作,比如单击clicked()

(2)、选择菜单“编辑”,找到Edit Signals/Slots,或者在工具栏中找到第二项(第二张图),然后拖动按钮并释放,

弹出“配置连接”选项,选择需要进行的操作即可。

(3)、自定义:以按钮为例,使用connect
在头文件中添加:
private slots:
void on_button1_clicked();
在.cpp文件下面的构造函数中添加:
connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(on_button1_clicked()));
接着实现槽函数即可。
(4)、不用写connect:
Qt信号和槽函数的命名是有规则的,组成为on_对象名_信号,以按钮为例,如果对象名为pushButton,在你在写槽函数的时候按照这种规则,则
在头文件中添加:
private slots:
void on_pushButton_clicked();
在.cpp文件下面的构造函数中就不用写connect了,直接写槽函数的实现就能实现信号和槽的连接。
07. 示例
最小的C ++类声明可能是:

  class Counter
  {
   
  public:
      Counter() {
    m_value = 0; }

      int value() const {
    return m_value; }
      void setValue(int value);

  private:
      int m_value;
  };

一个小的基于QObject的类可能是:

#
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值