我用一个信号连接一个插槽。但现在我想暂时断开它们。
以下是我的班级声明的一部分:
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()));
但是,在插槽on_btnDownload_clicked
中。我不希望myReadTimer
在on_btnDownload_clicked
的范围内发出任何信号。所以我想在on_btnDownload_clicked
的开头断开它们并最终重新连接它们。像这样:
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
析构函数。但我不知道如何使用它。
我还尝试使用disconnect
,例如:
QMetaObject::Connection myConnect;
myConnect=connect(myReadTimer,SIGNAL(timeout()),this,SLOT(ReadMyCom()));
...
disconnect(& myConnect);
但它仍然不起作用。那么任何人都可以帮我怎么做?
答案 0 :(得分:19)
QObject
中有一个非常好的功能,它不时地派上用场:QObject::blockSignals()
这是一个非常简单的即发即弃课程,可以做你想要的。我不相信它的设计,我很久以前就在互联网上找到了它。但要小心,它会阻止所有对象的所有信号。如果这不是您想要的,您可以修改课程以满足您的需求。
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
}
<强>更新强>
我从Qt 5.3中看到,一个非常类似的类被正式添加到API中。它的功能与上面的相似,功能稍大一些。我建议您使用官方QSignalBlocker课程,以便让您的代码库与最新的API保持同步。
但是,用法仍然完全相同。答案 1 :(得分:9)
有多种方法可以调用断开连接,具体取决于您要断开连接的内容。有关其工作原理的说明,请参阅the QObject documentation page。
这是一个使用0表示&#34;断开所有插槽的示例。&#34;
void frmMain::on_btnDownload_clicked()
{
// disconnect everything connected to myReadTimer's timeout
disconnect(myReadTimer, SIGNAL(timeout()), 0, 0);
...//the code that I want myReadTimer to leave me alone
// restore the connection
connect(myReadTimer,SIGNAL(timeout()),this,SLOT(ReadMyCom()));
}
或者您可以通过复制“连接”来指定要断开的确切信号 - 插槽对。语法,像这样:
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应用程序中,如果您已经处理过一个信号,那么另一个信号就不会在中间跳转#34;那段代码。相反,它会在当前时隙返回后立即排队等待处理。
因此,您可能根本不需要停止或断开计时器。
与原始方法的差异:
on_btnDownload_clicked
需要一段时间才能执行,那么在ReadMyCom
完成后,您可能会排队多个on_btnDownload_clicked
个事件。 (注意,在这一点上,你有一个基本上&#34;锁定&#34;你的GUI一段时间的操作;重构函数或给它自己的线程更有意义。)< / LI>