Qt为自己的程序建立一个消息循环

  • 一般事件循环都是由exec()来开启的,如:
QCoreApplicaton::exec()
QApplication::exec()
QDialog::exec()
QThread::exec()
QDrag::exec()
QMenu::exec()
  • 事件循环是一个无限循环,程序在exec()里面无限循环,能让跟在exec()后面的代码得不到运行的机会,直到exec()跳出。从exec()中跳出时,事件循环会被终止。QEventLoop::quit()能够终止事件循环。事件循环实际上类似于一个事件队列,对列入的事件依次的进行处理,当时间做完而事件循环没有结束的时候,其实际上比较类似于一个不占用CPU事件的for(;;)循环。
  • 事件循环是可以嵌套的,当在子事件循环中的时候,父事件循环中的事件实际上是处于中断的状态,当子循环跳出exec()之后才可以执行父循环中的事件。但是此时并不代表父循环中的界面响应会被中断,因为往往子循环中也会有父循环的大部分事件,执行QMessageBox::exec(),QEventLoop::exec()的时候,虽然这些exec()打断了main函数中的QApplication::exec(),但是由于GUI界面的响应已经被包含在子循环当中,所以GUI界面依然能够得到响应。
  • 如果某一个子事件的循环仍然有效,但是其父循环被强制跳出,此时父循环不会立即执行跳出,而是等待子事件循环跳出后,父循环才会跳出。

如果希望将主线程等待100ms,不能使用sleep来完成这个过程,那样会导致GUI界面停止响应。但是利用事件循环就可以避免这一点:

QEventLoop loop;
QTimer::singleShot(100,&loop,SLOT(quit()));
loop.exec();

若在一个槽函数中创建一个对象如下:

void myDialog:: on_pushButton_clicked()
{
  QDialog dlg;
  dlg.show();
}

此时我们会看不到dlg窗口或者是看到窗口一闪而过。因为我们的dlg会因为出了作用域而被析构掉。解决的办法很简单。

  1. 将 dlg 作为类的成员,而不是函数的局部变量
  2. 将 dlg 前添加static作为静态成员
  3. 将 dlg 用new分配到heap当中
  4. 使用事件循环
void myDialog::on_pushButton_clicked()
{
  QDialog tDlg;
  tDlg.show();
  QEventLoop tloop;
  connect(&tDlg,SIGNAL(finished(int)),&tloop,SLOT(quit()));
  tloop.exec(QEventLoop::AllEvents);
}

你可能感兴趣的:(Qt为自己的程序建立一个消息循环)