【问题标题】:QMessageBox halts QTimerQMessageBox 停止 QTimer
【发布时间】:2013-02-03 19:00:10
【问题描述】:

我创建了一个QMessageBox 实例,在连接到QTimer 信号timeout() 的插槽中使用单个按钮“OK”并使用exec 函数显示它,似乎计时器暂停直到按下按钮并关闭框。我希望exec 创建本地事件循环并发送定时器消息,但是定时器被暂停(没有信号timeout() 发出)。谁能解释一下? P.S 对不起我的英语。

更新: 示例代码:

#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;
}

【问题讨论】:

  • 在答案中查看我的编辑。

标签: qt


【解决方案1】:

好吧,您可以看到事件循环正在运行,因为timer1 正在触发超时。从documentation 你可以看到exec() 正在阻塞调用——所以它会阻塞调用函数(QTimer 槽)直到对话框关闭。

这将我们引向QObject 源代码。执行槽函数后,在QMetaObject::activate,最后一步是重置信号的发送者:

QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);

这将重置QTimer 状态,并重新开始倒计时。我认为这是确保定时器回调按顺序调用的常识性方法——就像大多数 UI 库中的定时器一样,而不是在 same 定时器中并行调用。

因为exec() 会阻塞定时器回调,QTimer 不会被重置,回调也不会被再次调用(直到函数恢复,QTimer 被重置)。

你有几种方法来处理这个:

1) 如果您不希望您的函数被阻塞,并且您不需要模态对话框的结果来继续该函数 - 调用 QMessageBox::open() 而不是 QMessageBox::exec() - 它不会阻塞调用者函数。

2)如果您需要对话框的结果来继续该功能,并且您不想停止计时器回调,那么天真的方法是通过在输入时依次调用QTimer::stop()QTimer::start()手动重置QTimer回调函数。

【讨论】:

  • 谢谢,你很有帮助。我决定使用 QMessageBox::open。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-24
  • 2021-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-12
  • 1970-01-01
相关资源
最近更新 更多