我用一个信号连接一个插槽.但现在我想暂时断开它们.
这是我的班级声明的一部分:
class frmMain : public QWidget
{
...
private:
QTimer *myReadTimer;
...
private slots:
void on_btnDownload_clicked();
...
};
Run Code Online (Sandbox Code Playgroud)
在构造函数中frmMain
,我连接myReadTimer
一个插槽,以便ReadMyCom
每5秒调用一次:
myReadTimer=new QTimer(this);
myReadTimer->setInterval(5000);
connect(myReadTimer,SIGNAL(timeout()),this,SLOT(ReadMyCom()));
Run Code Online (Sandbox Code Playgroud)
但是,在插槽中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
}
Run Code Online (Sandbox Code Playgroud)
我在Stackoverflow中搜索并获得了一些答案,比如调用QObject
析构函数.但我不知道如何使用它.
我也试过用disconnect
,比如:
QMetaObject::Connection myConnect;
myConnect=connect(myReadTimer,SIGNAL(timeout()),this,SLOT(ReadMyCom()));
...
disconnect(& myConnect);
Run Code Online (Sandbox Code Playgroud)
但它仍然无效.那么任何人都可以帮我怎么做?
Rob*_*ieE 21
有一个非常好的功能,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;
};
Run Code Online (Sandbox Code Playgroud)
在您的情况下,使用变得微不足道
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
}
Run Code Online (Sandbox Code Playgroud)
更新:
我从Qt 5.3中看到,一个非常类似的类被正式添加到API中.它的功能与上面的相似,功能稍大一些.我建议您使用官方的QSignalBlocker类,以使您的代码库与任何API更改保持同步.
但是,用法仍然完全相同.
Ale*_*x P 11
有多种方法可以调用断开连接,具体取决于您要断开连接的内容.有关它们如何工作的说明,请参阅QObject文档页面.
这是一个使用0表示"断开所有插槽"的示例.
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()));
}
Run Code Online (Sandbox Code Playgroud)
或者,您可以通过复制"connect"语法来指定要断开的确切信号槽对,如下所示:
disconnect(myReadTimer,SIGNAL(timeout()),this,SLOT(ReadMyCom()));
Run Code Online (Sandbox Code Playgroud)
由于您正在使用计时器,这可能更简单:
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();
}
Run Code Online (Sandbox Code Playgroud)
与您原来的方法不同:
interval
您的插槽功能将完成.在单线程Qt应用程序中,如果您已经在处理信号,则另一个信号将不会"跳到该代码的中间".相反,它会在当前时隙返回后立即排队等待处理.
因此,您可能根本不需要停止或断开计时器.
与您原来的方法不同:
on_btnDownload_clicked
需要一段时间才能执行,您可能会ReadMyCom
在on_btnDownload_clicked
完成后排队多个事件.(注意,此时你的操作基本上会"锁定"你的GUI一段时间;重构函数或给它自己的线程更有意义.)