【问题标题】:SIGNAL & SLOT macros in Qt : what do they do?Qt 中的 SIGNAL 和 SLOT 宏:它们有什么作用?
【发布时间】:2019-12-02 06:16:51
【问题描述】:

我是 Qt 的初学者,并试图理解 SIGNALSLOT 宏。在学习使用connect方法绑定信号和槽的时候,发现Qt官方参考页上的教程使用:

connect(obj1, SIGNAL(signal(int)), obj2, SLOT(slot()))

不过,这也很有效:

connect(obj1, &Obj1::signal, obj2, &Obj2::slot)

那么宏 SIGNALSLOT 究竟是做什么的?他们只是在对象所属的类中查找信号并返回它的地址吗?

那为什么大多数程序员都使用这些宏而不是使用&Obj1::signal,因为后者看起来更简单,如果信号函数的参数发生变化,您不需要更改代码?

【问题讨论】:

    标签: qt macros signals slot


    【解决方案1】:

    在 Qt 5 之前,使用 SIGNALSLOT 宏曾经是建立连接的唯一方法。连接是在运行时建立的,并且需要在标头中标记信号和插槽。例如:

    Class MyClass : public QObject
    {
        Q_OBJECT
        signals:
            void Signal();
    
        slots:
            void ASlotFunction();
    };
    

    为避免重复,描述了它的工作方式in the QT 4 documentation

    信号和槽机制是 Qt 提供的 C++ 扩展的一部分,它使用了Meta Object Compiler (moc)

    This 解释了为什么信号和插槽使用 moc。

    第二个连接方法得到了很大改进,因为指定的函数可以在编译时检查,而不是运行时检查。此外,通过使用函数的地址,您可以引用任何类函数,而不仅仅是标记为 slots:

    部分的那些函数

    documentation was updated for Qt 5

    此外,还有一篇关于 Qt 4 连接工作 here 和 Qt 5 here 的好博文。

    【讨论】:

      【解决方案2】:

      第一个答案的补充。

      宏 SIGNAL 和 SLOT 究竟做了什么

      几乎没有。看qobjectdefs.h

      # define SLOT(a)     "1"#a
      # define SIGNAL(a)   "2"#a
      

      它只是添加了12。这意味着下一个代码是有效的并且按预期工作:

      QObject *obj = new QObject;
      connect(obj,"2objectNameChanged(QString)",this,"1show()");//suppose this is a pointer to a QDialog subclass
      obj->setObjectName("newNAme");
      

      为什么大多数程序员使用这些宏而不是使用 like &Obj1::信号

      More details here.

      【讨论】:

      • 你真的是想说“这些宏不仅在Qt5中工作”吗?还是别的什么?
      • @PeterMortensen 是的,因为宏方式在 Qt4 和 Qt5 中有效,但是通过指针指向方法的新方式仅在 Qt5 中有效,所以这就是为什么我这样写的原因,那些使用传统的开发人员旧代码不能使用 Qt5,所以他们不能使用新方式,所以他们使用“不仅在 Qt5 中工作”的旧方式
      【解决方案3】:

      要完成TheDarkKnight's answer,使用函数地址将使用旧 Qt 4 SIGNAL 和 SLOT 宏的遗留代码重构为 Qt 5 的新语法是一种极好的做法。

      突然间,连接错误将出现在编译时而不是运行时!很容易出现 Qt 4 连接错误,因为任何拼写错误都会导致这样的错误。另外,函数的名称必须是完全限定的名称,即前面有完整的命名空间(如果有)。

      另一个好处是槽函数可以使用 lambda,如果槽体是微不足道的,这可以减少对命名函数的需求。

      【讨论】:

        【解决方案4】:

        这些宏只是将它们的参数转换为信号/槽特定的字符串。 Differences between String-Based and Functor-Based Connections 可以在文档中找到。简而言之:

        基于字符串:

        • 类型检查在运行时完成
        • 可以将信号连接到参数多于信号的槽(使用默认参数)
        • 可以将 C++ 函数连接到 QML 函数

        基于函子的:

        • 类型检查在编译时完成
        • 可以执行隐式类型转换
        • 可以将信号连接到 lambda 表达式

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-04-20
          • 1970-01-01
          相关资源
          最近更新 更多