- 一般事件循环都是由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会因为出了作用域而被析构掉。解决的办法很简单。
- 将 dlg 作为类的成员,而不是函数的局部变量
- 将 dlg 前添加static作为静态成员
- 将 dlg 用new分配到heap当中
- 使用事件循环
void myDialog::on_pushButton_clicked()
{
QDialog tDlg;
tDlg.show();
QEventLoop tloop;
connect(&tDlg,SIGNAL(finished(int)),&tloop,SLOT(quit()));
tloop.exec(QEventLoop::AllEvents);
}