Qt EventLoop建立一个局部的local event loop,但网上普遍就此结论,却没有阐述深入理解。
目录
event loop?
Qt EventLoop::exec介绍:
Enters the main event loop and waits until exit() is called. Returns the value that was passed to exit().
If flags are specified, only events of the types allowed by the flags will be processed.
It is necessary to call this function to start event handling. The main event loop receives events from the window system and dispatches these to the application widgets.
Generally speaking, no user interaction can take place before calling exec(). As a special case, modal widgets like QMessageBox can be used before calling exec(), because modal widgets use their own local event loop.
To make your application perform idle processing (i.e. executing a special function whenever there are no pending events), use a QTimer with 0 timeout. More sophisticated idle processing schemes can be achieved using processEvents().
翻译:
通过调用 EventLoop::exec函数,将启用事件处理。以便接收系统事件,以及派发事件到部件中,通常没有用户交互的时候,才调用exec(),当然这也有例外,例如QMessage Box ,模态部件有自己的事件循环。
翻译总结:
eventloop是用来系统事件接收和派送事件。
那什么时候需要使用Qeventloop?
答:没有事件循环,但要事件循环的时候,或者 延迟,但不能阻塞GUI线程时等。GUI线程设计是响应用户交互,其耗时,睡眠函数等任务最好不要在GUI主线程中,以避免阻塞主线程。通常可以这样休眠:
1.
QTime time;
time.start();while(time.elapsed() < 5000) //等待时间流逝5秒钟
QCoreApplication::processEvents(); //处理事件
2.
QEventLoop eventloop;
QTimer::singleShot(5000, &eventloop, SLOT(quit()));
eventloop.exec();
怎么判断没有事件循环?eventloop是如何划分的?
Qt thread中介绍:
Per-Thread Event Loop
Each thread can have its own event loop. The initial thread starts its event loop using QCoreApplication::exec(), or for single-dialog GUI applications, sometimes QDialog::exec(). Other threads can start an event loop using QThread::exec(). Like QCoreApplication, QThread provides an exit(int) function and a quit() slot.
An event loop in a thread makes it possible for the thread to use certain non-GUI Qt classes that require the presence of an event loop (such as QTimer, QTcpSocket, and QProcess). It also makes it possible to connect signals from any threads to slots of a specific thread. This is explained in more detail in the Signals and Slots Across Threads section below.
A QObject instance is said to live in the thread in which it is created. Events to that object are dispatched by that thread's event loop. The thread in which a QObject lives is available using QObject::thread().
The QObject::moveToThread() function changes the thread affinity for an object and its children (the object cannot be moved if it has a parent).
翻译总结:
每一个线程都有自己的事件循环,通过exec启用事件循环。线程中事件循环使得那些非GUI但需要事件循环的类能够正常运行,例如(QTimer,QTcpSocket)。也使得任何线程的信号能够连接一个特定线程的槽(意思:槽所在的线程中有event loop,那么其他线程信号就可以关联该槽)。
QObject在哪个线程中创建,就在那个线程中生存,派送到QObject的事件通过该线程的event loop所派送。从上图可以看出,线程中event loop不能被其他线程复用。
使用实例:
重写run函数,但无事件循环,能发信号,但thread内部槽函数不能使用。
#include <QCoreApplication>
#include "mythread.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Mythread th;
QObject::connect(&th,&Mythread::timeout,[=]()mutable{
qDebug() << "timeout";
});
QObject::connect(&th,&Mythread::threadheart,[=]()mutable{
qDebug() << "threadheart";
});
th.start();
return a.exec();
}
#include "mythread.h"
#include <QEventLoop>
Mythread::Mythread()
{
}
void Mythread::run()
{
QTimer timer;
timer.setInterval(1000);
connect(&timer,SIGNAL(timeout()),this,SIGNAL(timeout()));
timer.start();
while(1)
{
emit threadheart();
}
}
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QObject>
#include <QTimer>
class Mythread : public QThread
{
Q_OBJECT
public:
Mythread();
void run () override;
signals:
void threadheart();
void timeout();
};
#endif // MYTHREAD_H
重写run函数,添加local事件循环,能发信号,thread内部槽函数能使用。
#include "mythread.h"
#include <QEventLoop>
Mythread::Mythread()
{
}
void Mythread::run()
{
QTimer timer;
timer.setInterval(1000);
connect(&timer,SIGNAL(timeout()),this,SIGNAL(timeout()));
timer.start();
while(1)
{
emit threadheart();
QEventLoop eventloop; //添加事件循环。
QTimer::singleShot(1000, &eventloop, SLOT(quit()));
eventloop.exec();
}
}