如何在Qt中临时断开带有插槽的信号?

如何在Qt中临时断开带有插槽的信号?,qt,signals-slots,Qt,Signals Slots,我用信号连接插槽。但现在我想暂时断开它们的连接 这是我的班级宣言的一部分: class frmMain : public QWidget { ... private: QTimer *myReadTimer; ... private slots: void on_btnDownload_clicked(); ... }; 在frmMain的构造函数中,我将myReadTimer与插槽连接,以便每隔5秒调用ReadMyCom: myReadTimer=ne

我用信号连接插槽。但现在我想暂时断开它们的连接

这是我的班级宣言的一部分:

class frmMain : public QWidget
{
    ...
private:
    QTimer *myReadTimer;
    ...
private slots:
    void on_btnDownload_clicked();
    ...
};
frmMain
的构造函数中,我将
myReadTimer
与插槽连接,以便每隔5秒调用
ReadMyCom

myReadTimer=new QTimer(this);
myReadTimer->setInterval(5000);
connect(myReadTimer,SIGNAL(timeout()),this,SLOT(ReadMyCom()));
但是,在卸载时的插槽
中单击了
。我不想
myReadTimer
在单击的
范围内发出任何信号。因此,我想在单击的
上的的开头断开它们的连接,并在最后重新连接它们。像这样:

void frmMain::on_btnDownload_clicked()
{
    //some method to disconnect the slot & singal

    ...//the code that I want myReadTimer to leave me alone

    //some method to reconnect the slot & singal
}
我在Stackoverflow中搜索,得到了一些答案,比如调用
QObject
析构函数。但我不知道如何使用它

我还尝试使用
断开连接
,例如:

QMetaObject::Connection myConnect;
myConnect=connect(myReadTimer,SIGNAL(timeout()),this,SLOT(ReadMyCom()));
...
disconnect(& myConnect);
但它仍然不起作用。有人能帮我怎么做吗?

断开/重新连接语法 有许多方法可以调用disconnect,具体取决于您想要断开连接的内容。有关其工作原理的说明,请参阅

下面是一个使用0表示“断开所有插槽”的示例

或者,您可以通过复制“connect”语法来指定要断开的确切信号插槽对,如下所示:

disconnect(myReadTimer,SIGNAL(timeout()),this,SLOT(ReadMyCom()));
停止计时器 由于您使用的是计时器,这可能更简单:

void frmMain::on_btnDownload_clicked()
{
    // stop the timer (so you won't get any timeout signals)
    myReadTimer->stop();    

    ...//the code that I want myReadTimer to leave me alone

    // restart the timer (using whatever interval was set previously)
    myReadTimer->start();
}
与原始方法的不同之处:

  • 由于您正在停止并重新启动计时器,因此下次触发计时器的时间将是插槽功能完成后的
    interval
你需要做什么特别的事吗? 在单线程Qt应用程序中,如果您已经在处理一个信号,那么另一个信号不会“跳到”代码的中间。相反,它将作为偶数排队,以便在当前插槽返回后立即处理

因此,也许你根本不需要停止或断开计时器

与原始方法的不同之处:

  • 如果单击卸载时的
    需要一段时间才能执行,则在单击卸载时的
    完成后,可能会有多个
    ReadMyCom
    事件排队。(请注意,此时您的操作基本上会“锁定”GUI一段时间;重构函数或为其提供自己的线程可能更有意义。)

QObject
中有一个非常好的函数,它经常派上用场:
QObject::blockSignals()

这是一个非常简单的fire-and-forget类,它可以满足您的需要。我不相信它的设计,我很久以前在网上的某个地方找到了它。不过要小心,它会阻止所有对象的所有信号。如果这不是您想要的,您可以修改该类以满足您的需要

class SignalBlocker{
public:
    SignalBlocker(QObject *o): object(o), alreadyBlocked(object->signalsBlocked()){
        if (!alreadyBlocked){
            object->blockSignals(true);
        }
    }
    ~SignalBlocker() {
        if (!alreadyBlocked){
            object->blockSignals(false);
        }
    }

private:
    QObject *object;
    bool alreadyBlocked;
};
在您的情况下,使用变得微不足道

void frmMain::on_btnDownload_clicked()
{
    SignalBlocker timerSignalBlocker(myReadTimer);

    ...//the code that I want myReadTimer to leave me alone

    // signals automatically unblocked when the function exits
}
更新:

我从Qt5.3中看到,一个非常类似的类已经正式添加到API中。它的功能集稍大,与上面的功能集类似。我建议您改用官方类,以使您的代码库在任何API更改时保持最新


但是,用法仍然完全相同。

您是否查看了
断开连接的文档?它采用与connect相同的参数。我阅读了disconnect的文档,发现了staticbooldesconnect(constqmetaobject::Connection&)那么我是怎么错的呢?您使用QObject::disconnect()的示例是正确的,除了示例在预期引用的位置传递一个指针,所以它甚至不应该编译<代码>断开连接(myConnect)
工作。
void frmMain::on_btnDownload_clicked()
{
    SignalBlocker timerSignalBlocker(myReadTimer);

    ...//the code that I want myReadTimer to leave me alone

    // signals automatically unblocked when the function exits
}