Qt:如何通过像函数一样调用信号来知道slot是否被信号-槽机制调用



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

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

您可以在这两种情况下检查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();
}

输出:

测试(0 xa8e8aff5b0)

QObject (0 x0)

  1. 添加一个默认参数到您的插槽:

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

    void MyClass::method()
    {
        [...]
        slot(false);
        [...]
    }
    
  3. 保持connect()呼叫不变;

  4. 不给信号增加bool参数,也不将SLOT(slot())改为SLOT(slot(bool))

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

如果您的插槽不需要是公共的,因为connect()只从类内部处理它,您应该将其设置为私有并添加一个要调用的包装器方法,但是在从类内部调用它时仍然需要一些规则。Johannes的建议将解决这些问题。

另一种区分直接函数调用与信号/槽调用的方法:

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

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

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

参见Qt 4.8文档

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

问候,Felix

最新更新