我创建了一个QMessageBox实例,在连接到QTimer signal timeout()的插槽中有一个"OK“按钮,并使用exec函数显示它,似乎计时器停止工作,直到按钮按下,盒子关闭。我期望exec创建本地事件循环并发送计时器消息,但是计时器被暂停(没有发出信号timeout() )。有人能解释吗?对不起,我的英语。
更新:示例代码:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QTimer *tm1=new QTimer(this),
*tm2=new QTimer(this);
connect(tm1,SIGNAL(timeout()),this,SLOT(tslot1()));
connect(tm2,SIGNAL(timeout()),this,SLOT(tslot2()));
tm1->start(1000);
tm2->start(1000);
}
void MainWindow::tslot1(void)
{
static int cnt;
qWarning(QString("slot 1 called %1 time(s)").arg(++cnt).toAscii().data());
}
void MainWindow::tslot2(void)
{
static int cnt;
qWarning(QString("slot 2 called %1 time(s)").arg(++cnt).toAscii().data());
if (3==cnt)
{
QMessageBox *mb=new QMessageBox(QMessageBox::Critical,tr("Error"),tr("tm2 halted !"),QMessageBox::Ok,this);
mb->exec();
}
}
MainWindow::~MainWindow()
{
delete ui;
}发布于 2013-02-03 23:39:01
您可以看到事件循环正在运行,因为timer1正在触发超时。从文档中可以看到,exec()阻塞了调用,因此它将阻塞调用方函数(QTimer时隙),直到对话框关闭。
这就引出了QObject源代码。执行插槽功能后,在QMetaObject::activate中,最后一步是重置信号的发送方:
QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender);
这将重置QTimer状态,并将再次开始倒计时。我认为这是确保在大多数UI库中按顺序调用定时器回调的常识方法,而不是在相同的计时器中并行调用。
因为exec()会阻止计时器回调,所以QTimer不会被重置,回调也不会再次被调用(直到函数恢复,QTimer得到它的重置)。
您有几种处理此问题的方法:
1)如果您不想阻止您的函数,并且不需要模态对话框的结果来继续进行函数--调用QMessageBox::open()而不是QMessageBox::exec() --它将不会阻塞调用函数。
2)如果您需要对话框的结果来继续这个函数,并且您不想停止您的计时器回调,那么简单的方法是在输入回调函数时通过依次调用QTimer和QTimer::start()来手动重置QTimer::stop()和QTimer::start()。
https://stackoverflow.com/questions/14676085
复制相似问题