搜索
您的当前位置:首页正文

Qt的事件循环机制

来源:知库网
Qt的事件循环机制

参考:

1 ⼀般我们的事件循环都是由exec()来开启的,例如下⾯的例⼦:

1 QCoreApplicaton::exec()2 QApplication::exec()3 QDialog::exec()4 QThread::exec()5 QDrag::exec()6 QMenu::exec()

  这些都开启了事件循环,事件循环⾸先是⼀个⽆限“循环”,程序在exec()⾥⾯⽆限循环,能让跟在exec()后⾯的代码得不到运⾏机会,直⾄程序从exec()跳出。从exec()跳出时,事件循环即被终⽌。QEventLoop::quit()能够终⽌事件循环。

事件循环实际上类似于⼀个事件队列,对列⼊的事件依次的进⾏处理,当时间做完⽽时间循环没有结束的时候,其实际上⽐较类似于⼀个不占⽤CPU事件的for(;;)循环。

  其本质实际上是以队列的⽅式来重新分配时间⽚。

2.事件循环是可以嵌套的,当在⼦事件循环中的时候,⽗事件循环中的事件实际上处于中断状态,当⼦循环跳出exec之后才可以执⾏⽗循环中的事件。当然,这不代表在执⾏⼦循环的时候,类似⽗循环中的界⾯响应会被中断,因为往往⼦循环中也会有⽗循环的⼤部分事件,执⾏

QMessageBox::exec(),QEventLoop::exec()的时候,虽然这些exec()打断了main()中的

QApplication::exec(),但是由于GUI界⾯的响应已经被包含到⼦循环中了,所以GUI界⾯依然能够得到响应。

3.如果某个⼦事件循环仍然有效,但其⽗循环被强制跳出,此时⽗循环不会⽴即执⾏跳出,⽽是等待⼦事件循环跳出后,⽗循环才会跳出

举⼏个例⼦吧,⽐如说如果想要将主线程等待100ms,总不能使⽤sleep吧,那样会导致GUI界⾯停⽌响应的,但是⽤事件循环就可以避免这⼀点:

1 QEventLoop loop;

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

还有,⽐如说对于⼀个槽函数,触发之后会弹出⼀个dialog,但是像下⾯这样写的话,窗⼝会⼀闪⽽过的:

1 void ****::mySLot{2 QDialog dlg;3 dlg.show();4 }

当然这⾥可以使⽤将dlg改成⼀个静态成员,通过增长期⽣存期的⽅法来解决这个问题,但是这⾥同样可以使⽤eventLoop来解决这个问题:

1 void ****::mySLot{2 QDialog dlg;3 dlg.show();

4 QEventLoop loop;

5 connect(&dlg, SIGNAL(finished(int)), &loop, SLOT(quit()));6 loop.exec(QEventLoop::ExcludeUserInputEvents);7 }

将dlg写⼊事件循环中,因为此时dlg的活动只是show,没⽤调⽤任何资源,这种等待状态可以与其它事件并存,其它事件仍能触发;直到dlg发出finished信号,退出事件循环,代码继续向下执⾏。

QEventLoop

At any time, you can create a QEventLoop object and call exec() on it to start a local event loop. From within the event loop,calling exit() will force exec() to return.退出⽅法⽅法⼀:

QEventLoop loop;...

QNetworkReply *postReply = m_pNetManager->post(request, qbt); //post⽅式到本地服务器

connect(postReply, SIGNAL(finished()), this, SLOT(postFileReplyFinished())); //成功后会有返回响应loop->exec(); //设置等待,若⽂件成功发送,则退出等待...

//在其他的响应函数中退出循环

void Widget::postFileReplyFinished(){

QNetworkReply* reply = (QNetworkReply*)sender(); QByteArray replyData = reply->readAll();

//转为JSon格式,便于提取字段数据

QJsonDocument jsonDoc= QJsonDocument::fromJson(replyData);

if(!jsonDoc.isNull()) {

QJsonObject jsonObj = jsonDoc.object(); //转换格式 if(jsonObj.contains(\"status\")) {

loop->exit(); //loop退出等待 } }}

⽅法⼆

QEventLoop loop;

qManager = new QNetworkAccessManager(this);QNetworkRequest request;

request.setUrl(QUrl(\"http://localhost/public/index/file/upload\"));QNetworkReply *reply = qManager->get(request);

connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));loop.exec();

这样的话就更简洁了。可是有个问题就是,⼀收到reply就退出事件的循环,如果想要判断⼀下还是⽤前⾯的⽅法⽐较好

因篇幅问题不能全部显示,请点此查看更多更全内容

Top