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

1、介绍

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

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

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

2、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

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

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

 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,则后面的槽都不会响应。
  一个类内部静态函数只能存在一种信号,如果有多种信号,则除了第一个外,后面的都没响应。

解决方案
  在信号上加个枚举变量,用来区分信号的类别,并将此信号关联到另外一个非静态函数的槽中,然后在这个槽中通过枚举变量发送不同信号。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt,发送信号是通过信号机制来实现的。通常情况下,信号由一个对象触发并由另一个对象接收。 然而,有时候我们希望在没有实例化对象的情况下发送信号,这时就可以使用静态函数来发送信号静态函数是类的成员函数,但它不依赖于任何特定的对象实例。 要在静态函数发送信号,需要使用到`QMetaObject::invokeMethod`函数。首先,需要获取到发送信号的类的元对象(Meta Object)。然后使用`invokeMethod`函数来调用该静态函数,并传递相应的参数。 假设我们有一个类`MyClass`,其包含一个静态函数`static void sendMessage(const QString& message)`,我们可以使用以下代码来发送信号: ```cpp QMetaObject::invokeMethod(MyClass::staticMetaObject, "sendMessage", Q_ARG(QString, "Hello, World!")); ``` 上述代码,`staticMetaObject`是`MyClass`的元对象。`"sendMessage"`是我们要调用的静态函数的名称。`Q_ARG(QString, "Hello, World!")`是传递给静态函数的参数。 在接收信号的地方,可以像接收普通的信号一样使用连接函数(`connect`)来连接到这个静态函数。 需要注意的是,由于静态函数不依赖于对象实例,因此在静态函数不能直接访问非静态的成员变量或成员函数。如果需要在静态函数使用这些成员,可以通过额外的参数传递进来。 总之,通过使用`QMetaObject::invokeMethod`函数,我们可以在静态函数发送信号,并在其他地方接收该信号。这样可以灵活地使用信号机制,即使没有实例化对象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值