QT事件循环类QEventLoop, Qt作为一个跨平台的UI框架,其事件循环实现原理, 就是把不同平台的事件循环进行了封装,并提供统一的抽象接口。 Application类中,除去启动参数、版本等相关东西后,关键就是维护了一个QEventLoop,Application的exec就是QEventLoop的exec。不过Application中的这个EventLoop,我们称作“主事件循环”Main EventLoop。一般我们的事件循环都是由exec()来开启的,如下:
QCoreApplicaton::exec()
QApplication::exec()
QDialog::exec()
QThread::exec()
QDrag::exec()
QMenu::exec()
这些都开启了事件循环,事件循环首先是一个无限“循环”,程序在exec()里面无限循环,能让跟在exec()后面的代码得不到运行机会,直至程序从exec()跳出。从exec()跳出时,事件循环即被终止。QEventLoop::quit()能够终止事件循环。事件循环实际上类似于一个事件队列,对列入的事件依次的进行处理,当时间做完而时间循环没有结束的时候,其实际上比较类似于一个不占用CPU时间的的for(;;)循环。其本质实际上是以队列的方式来重新分配时间片。
我在这里为啥要提这个事件循环,因为后面我要讲的跟这个有关系。
阻塞非阻塞等待UI说白了,就是UI卡住和不卡住的区别,比如主线程的一个while循环,如果不加任何处理就是阻塞等待:阻塞当前进程,直到延时结束,方可进行其他操作(此时如果有界面,界面会卡住),UI就会卡死,写法如下:
方法1:
void sleepMsecSuspend(int msec)
{
QThread::msleep(2000);
}
方法2:
void sleepMsecSuspend(int msec)
{
QTime curTimer = QTime::currentTime();
QTime nowTimer;
do
{
nowTimer = QTime::currentTime();
} while (curTimer.msecsTo(nowTimer) <= msec);
}
方法3:
void sleepMsecSuspend(int msec)
{
QElapsedTimer t;
t.start();
while (t.elapsed() < msec);
}
非阻塞等待一段时间:在延时的过程中,可以进行其他操作,保证界面不会卡住,写法有如下
方法1:定义一个事件循环,用exec开启,需要退出的时候,用quit函数
void sleepMsec(int msec)
{
QEventLoop loop; //定义一个新的事件循环
QTimer::singleShot(msec, &loop, SLOT(quit()));//创建单次定时器,槽函数为事件循环的退出函数
loop.exec(); //事件循环开始执行,程序会卡在这里,直到定时时间到,本循环被退出
}
方法2:和线程一样,但这里不用Qthread,这里用QApplication::processEvents函数
void sleepMsec(int msec)
{
QTime curTimer = QTime::currentTime().addMSecs(msec);
while (QTime::currentTime() < curTimer)
{
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}
}
版权归原作者 Burt_Wu 所有, 如有侵权,请联系我们删除。