对于QCoreApplication,QGuiApplication以及QApplication,我一直分的不是很清楚,今天来梳理一下,并顺便记一些相关的笔记。
以下内容全部是自己的理解,有不正确的地方,欢迎大佬指出!
QCoreApplication
QCoreApplication位于core模块,源码在Src\qtbase\src\corelib\kernel目录下,为应用程序提供了一个非gui的事件循环。
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
return a.exec();
}
在程序中,我们只实例化一个QCoreApplication,然后调用exec()进入事件循环,我们看一下具体做了什么。
int QCoreApplication::exec()
{
if (!QCoreApplicationPrivate::checkInstance("exec"))
return -1;
QThreadData *threadData = self->d_func()->threadData;
if (threadData != QThreadData::current()) {
qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className());
return -1;
}
if (!threadData->eventLoops.isEmpty()) {
qWarning("QCoreApplication::exec: The event loop is already running");
return -1;
}
threadData->quitNow = false;
QEventLoop eventLoop;
self->d_func()->in_exec = true;
self->d_func()->aboutToQuitEmitted = false;
int returnCode = eventLoop.exec();
threadData->quitNow = false;
if (self)
self->d_func()->execCleanup();
return returnCode;
}
从代码中可以看出,我们只能在主线程中调用QCoreApplication的exec()接口。
在ecec()中,创建了一个事件循环eventLoop,调用了eventLoop.exec(),我们来看下做了什么。
// remove posted quit events when entering a new event loop
QCoreApplication *app = QCoreApplication::instance();
if (app && app->thread() == thread())
QCoreApplication::removePostedEvents(app, QEvent::Quit);
while (!d->exit.loadAcquire())
processEvents(flags | WaitForMoreEvents | EventLoopExec);
ref.exceptionCaught = false;
return d->returnCode.load();
从代码中可以看出QCoreApplication可以算是个单例类。在这个接口里,调用了processEvents进行事件分发,对于不同的平台有着不同的实现,以满足跨平台的需求。
关于接下来如何进行事件的post和send,留待以后的篇幅,我们再看看QCoreApplication有哪些常用的接口。
static QCoreApplication *instance(),等同于qApp宏,可以获取到QCoreApplication的指针。 void aboutToQuit(QPrivateSignal),是个私有信号,不能主动触发,该信号会在应用程序将要退出事件循环时发出,比如调用了quit()或者exit(0)的时候触发,可以进行一些程序的扫尾工作。 static void exit(int retcode=0),停止事件循环,一般回退出程序,其中quit()就是调用了exit(0)。 static qint64 applicationPid(),获取当前进程的pid。 static QString applicationDirPath(),获取执行文件所在的目录。 static QString applicationFilePath(),获取执行文件所在的位置。 static void setApplicationName(const QString &application),static QString applicationName(), 设置和获取应用程序的文件名; static void setApplicationVersion(const QString &version),static QString applicationVersion(),设置和获取应用程序的版本号;
QGuiApplication
QGuiApplication继承于QCoreApplication,位于gui模块中,其源码位于Src\qtbase\src\gui\kernel下。提供了额外的gui设置,比如桌面设置,风格,字体,调色板,剪切板,光标。QGuiApplication与QApplication的主要区别在于后者是基于QWidget的,如果我们开发程序,只有图形界面比如纯qml开发,并且不使用QWidget,就可以使用QGuiApplication,因为QApplication包含的东西很多,比较笨重。
int QGuiApplication::exec()
{
#ifndef QT_NO_ACCESSIBILITY
QAccessible::setRootObject(qApp);
#endif
return QCoreApplication::exec();
}
虽然使用QGuiApplication的时候也调用了exec(),但从源码可以看出它直接调用了QCoreApplication的exec()。
QGuiApplication还提供了会话管理,应用程序可以在用户注销时正常终止,如果无法终止则可以取消关闭进程,甚至可以保留整个应用程序的状态以备将来使用。
下面是常用的一些接口:
static void setApplicationDisplayName(const QString &name); static QString applicationDisplayName(); 设置和获取应用程序的可见名称。
static QScreen *primaryScreen(); 获取应用程序的主屏幕。
static void setWindowIcon(const QIcon &icon); static QIcon windowIcon(); 设置和获取应用程序的图标
static QList<QScreen *> screens(); 返回所有的窗口列表
static QObject *focusObject(); 返回当前活动窗口中的QObject,该QObject将是绑定到焦点的事件(如键事件)的最终接收者。
static QWindow *focusWindow(); 返回接收与焦点相关的事件(如键事件)的QWindow。
static QFont font();static void setFont(const QFont &); 获取和设置字体
static QWindow *modalWindow(); 返回最近显示的模态窗口。如果没有可见的模态窗口,这个函数返回0。
关于会话管理下次赘述。
QApplication
QApplication继承于QGuiApplication,位于widgets模块中,源码在Src\qtbase\src\widgets\kernel下,在QGuiApplication的基础上,特化了一些功能,主要体现在QWidget及其派生类中。优点是功能模块比较齐全,缺点是很笨重。
从源码上看,QApplication直接调用了QGuiApplication::exec()创建了事件循环。
而且QApplication增加了大量QWidget相关的函数,并且可以设置QT样式表。
由于很多都是QWidget相关的,以后再详细分析QWidget。