• Qt 静态函数中的信号和槽问题


    介绍
      信号和插槽用于对象之间的通信。信号和插槽机制是Qt的一个核心特性,可能是与其他框架提供的特性最为不同的部分。Qt的元对象系统使信号和插槽成为可能。

      在GUI编程中,当我们更改一个小部件时,我们通常希望通知另一个小部件。更一般地说,我们希望任何类型的对象都能够相互通信。例如,如果用户单击“关闭”按钮,我们可能希望调用窗口的 Close()函数。

      其他工具包使用回调实现这种通信。回调是指向函数的指针,因此如果希望处理函数通知您某个事件,请将指向另一个函数(回调)的指针传递给处理函数。处理函数然后在适当的时候调用回调。虽然使用此方法的成功框架确实存在,但是回调可能是非直观的,并且在确保回调参数的类型正确性方面可能会遇到问题。

    Qt中的信号和槽
      在Qt中,我们有一种回调技术的替代方法:使用信号和插槽。当特定事件发生时,会发出一个信号。Qt的小部件有许多预定义的信号,但是我们总是可以对小部件进行子类化,以便向它们添加我们自己的信号。插槽是响应特定信号而调用的函数。Qt的小部件有许多预定义的插槽,但通常的做法是对小部件进行子类化并添加自己的插槽,以便处理感兴趣的信号。(以上摘自Qt官方文档)

    一般形式
      下面为一般的信号槽形式。(案例摘自官方文档)

     1   // demo.h
     2   #include <QObject>
     3 
     4   class Counter : public QObject
     5   {
     6       Q_OBJECT                        // 必须要有
     7 
     8   public:
     9       Counter() { m_value = 0; }
    10 
    11       int value() const { return m_value; }
    12 
    13   public slots:
    14       void setValue(int value)
    15       {
    16           if (value != m_value) {
    17               m_value = value;
    18               emit valueChanged(value);
    19           }
    20       }    
    21 
    22   signals:
    23       void valueChanged(int newValue);
    24 
    25   private:
    26       int m_value;
    27   };
    28   
    29 
    30 //demo.cpp
    31   void Counter::setValue(int value)
    32   {
    33       if (value != m_value) {
    34           m_value = value;
    35           emit valueChanged(value);
    36       }
    37   }
    38       
    39   Counter a, b;
    40   QObject::connect(&a, &Counter::valueChanged, &b, &Counter::setValue);
    41 
    42   a.setValue(12);     // a.value() == 12, b.value() == 12
    43   b.setValue(48);     // a.value() == 12, b.value() == 48

    当发送信号的地方为静态函数时

    当发送信号的地方为静态函数时,采用上述形式会报错,此时发送信号的类需要添加一个静态指针才能使用。

     1 // demo.h
     2   #include <QObject>
     3 
     4   class Counter : public QObject
     5   {
     6       Q_OBJECT                            // 必须要有
     7 
     8   public:
     9       Counter() { m_value = 0; }
    10       static Counter* pointer_;            // 注意此处变化
    11       int value() const { return m_value; }
    12 
    13   public slots:
    14       static void setValue(int value)    // 要发送信号的地方为静态函数
    15       {
    16           if (value != m_value) {
    17               m_value = value;
    18               emit pointer_->valueChanged(value);    // 信号发送形式前面的加类静态指针引用
    19           }
    20       }    
    21       
    22   signals:
    23       void valueChanged(int newValue);
    24 
    25   private:
    26       int m_value;
    27   };
    28   
    29 
    30 //demo.cpp    用法
    31   Counter a, b;
    32   QObject::connect(&a, &Counter::valueChanged, &b, &Counter::setValue);
    33 
    34   a.setValue(12);     // a.value() == 12, b.value() == 12
    35   b.setValue(48);     // a.value() == 12, b.value() == 48

    存在问题
      上述信号只对代码执行第一次绑定的信号有效,如果多次connect,则后面的槽都不会响应。
      一个类内部静态函数只能存在一种信号,如果有多种信号,则除了第一个外,后面的都没响应。
    解决方案
      在信号上加个枚举变量,用来区分信号的类别,并将此信号关联到另外一个非静态函数的槽中,然后在这个槽中通过枚举变量发送不同信号。

  • 相关阅读:
    Q739.每日温度
    面试题46. 把数字成字符串
    [990. 等式方程的可满足性]--并查集
    [128. 最长连续序列]
    javaweb实现简单登陆功能
    7.12_python_lx_practise
    7.12_python_lx_day6
    7.12_python_lx_day5
    7.2_python_lx_day4
    7.2_python_lx_day3
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/16613310.html
Copyright © 2020-2023  润新知