【问题标题】:Qt: How to know if slot was called by signal-slot mechanism by calling the signal like a functionQt:如何通过像函数一样调用信号来知道信号槽机制是否调用了槽
【发布时间】:2016-09-04 07:30:13
【问题描述】:

在一个槽内,我检查了QObject::sender(),但现在我想像函数一样直接调用这个槽。

我能知道这个插槽是如何在插槽内部调用的吗?是通过信号槽机制还是简单地像函数一样调用槽?

【问题讨论】:

  • 将代码放入另一个具有bool fromSignal的函数中,并在您的插槽中使用true调用该其他函数,并在其他地方直接使用false调用它。
  • @JohannesSchaub-litb 我认为这将是一个很好的答案,比目前的答案更好。

标签: qt qt-signals qt-slot


【解决方案1】:
  1. 给你的槽添加一个默认参数:

    public slots:
        void slot(bool calledBySignal = true);
    
  2. 直接调用slot时设置参数为false:

    void MyClass::method()
    {
        [...]
        slot(false);
        [...]
    }
    
  3. connect() 呼叫保持原样;不要在信号中添加 bool 参数,也不要将 SLOT(slot()) 更改为 SLOT(slot(bool))

缺点:容易忘记设置参数。

如果您的插槽不需要公开,因为 connect()ing 仅在类内部处理,您应该将其设为私有并添加一个将被调用的包装器方法,但您仍然会从课堂内部调用它时需要一些纪律。 Johannes 的建议将解决这些问题。

【讨论】:

    【解决方案2】:

    您可以在这两种情况下查看sender()。如果通过信号/槽机制调用槽,发送方将返回一个指针,而当作为方法调用时,它将返回空指针。

    简单示例:

    class Test : public QObject
    {
        Q_OBJECT
    signals:
        void signal();
    
    public slots:
        void slot() { qDebug() << sender(); }
    };
    

    及用途:

    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        Test test;
        Test test2;
    
        QObject::connect(&test, &Test::signal, &test2, &Test::slot);
    
        test.signal(); //slot is caled by signal
        test2.slot(); //slot is called as method directly
    
        return a.exec();
    }
    

    还有输出:

    测试(0xa8e8aff5b0)

    QObject(0x0)

    【讨论】:

    • sender 作为方法调用时不为空
    • 文档中甚至有说明:“如果在由信号激活的槽中调用,则返回指向发送信号的对象的指针;否则返回 0。该指针仅在执行从这个对象的线程上下文调用这个函数的槽。” doc.qt.io/qt-5/qobject.html#sender
    • 这里的“如果在插槽中调用”大概是指“如果在插槽激活期间调用”。这意味着如果他直接“作为函数”调用插槽,但从另一个由信号调用的插槽,直接调用的插槽将观察到非空返回值。但这不是他想要的。如果不是无效,它会使您的解决方案有缺陷。
    【解决方案3】:

    区分直接函数调用与信号/插槽调用的另一个想法:

    使用方法 int QObject::senderSignalIndex() const 并检查 -1

    if(QObject::senderSignalIndex() == -1){
        //called directly as a function
    } else {
        // invoked via Signal/SLot mechanism
    }
    

    返回调用当前执行槽的信号的元方法索引,它是 sender() 返回的类的成员。如果在由信号激活的槽之外调用,则返回 -1。

    see Qt 4.8 documentation

    这看起来是一种清晰的区分方式,与使用 QObject * QObject::sender() const 相比,使用空指针不会遇到麻烦。

    问候, 费利克斯

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多