QtCoreApplication类整体结构

QtCoreApplication类整体结构

昨天偷懒了,没有进行源码分析,今天需要继续了。

今天的目的是从整体上对QtCoreApplication的设计结构进行分析,看看这个类到底是什么样子的。

首先进入该文件:src/corelib/kernel/qcoreapplication.h

首先预定义了我们经常需要的

#define qApp QCoreApplication::instance()方法。

下面是前向声明:

class QCoreApplicationPrivate;

class QTextCodec;

class QTranslator;

class QPostEventList;

class QStringList;

从这里可以看到一些关联,其中国际化的部分,字符集的部分,以及事件传递部分的类名被列在这里。

#include <QtCore/qobject.h>

#include <QtCore/qcoreevent.h>

#include <QtCore/qeventloop.h>

头文件还说明了事件循环以及控制台应用程序事件被使用。

该类继承自QObject,利用元对象系统为下面几个属性做了包装:

Q_PROPERTY(QString applicationName READ applicationName WRITE setApplicationName)

    Q_PROPERTY(QString applicationVersion READ applicationVersion WRITE setApplicationVersion)

    Q_PROPERTY(QString organizationName READ organizationName WRITE setOrganizationName)

    Q_PROPERTY(QString organizationDomain READ organizationDomain WRITE setOrganizationDomain)

至今对该类的好处不是很理解,唯一觉得有用的是Qt提供了当属性修改时发送信号的功能,其他的作用就不知道了,下面是我找到的一点解释:

qtforum上看到解释了……
这个宏主要是在自定义窗口部件(widget)的时候用,以通知desinger显示相应的可以修改的属性。这个宏是可以建立相应的读、写操作的,但是效果不见得好,原因在于有时我们所要的getset操作不是一个简单的=操作,还要做一些其他的工作。所以最好重写Q_PROPERTY里声明的这些函数

看来目前是不能理解到该宏的深刻内涵了,不能与设计者产生共鸣,等级不够啊。

好了,不感叹了,继续往下看:

Q_DECLARE_PRIVATE(QCoreApplication)

该宏定义是用来进行定义该类对应内部类的引用的。

static QStringList arguments();

 

    static void setAttribute(Qt::ApplicationAttribute attribute, bool on = true);

    static bool testAttribute(Qt::ApplicationAttribute attribute);

 

    static void setOrganizationDomain(const QString &orgDomain);

    static QString organizationDomain();

    static void setOrganizationName(const QString &orgName);

    static QString organizationName();

    static void setApplicationName(const QString &application);

    static QString applicationName();

这里摘录了一些静态方法,我们下面再做详细的研究。其中比较感兴趣的几个是:

static QStringList arguments();

static int exec();

static bool sendEvent(QObject *receiver, QEvent *event);

    static void postEvent(QObject *receiver, QEvent *event);

    static void postEvent(QObject *receiver, QEvent *event, int priority);

    static void sendPostedEvents(QObject *receiver, int event_type);

    static void sendPostedEvents();

    static void removePostedEvents(QObject *receiver);

    static void removePostedEvents(QObject *receiver, int eventType);

    static bool hasPendingEvents();

virtual bool notify(QObject *, QEvent *);

static bool startingUp();

    static bool closingDown();

接下来的一些函数为整个事件机制做准备:

#if defined(Q_WS_WIN)

    virtual bool winEventFilter(MSG *message, long *result);

#endif

 

#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)

    static void watchUnixSignal(int signal, bool watch);

#endif

typedef bool (*EventFilter)(void *message, long *result);

    EventFilter setEventFilter(EventFilter filter);

    bool filterEvent(void *message, long *result);

该类主要就这些东西了,我们再看下QCoreApplicationPrivate的头文件声明:

class Q_CORE_EXPORT QCoreApplicationPrivate : public QObjectPrivate

{

    Q_DECLARE_PUBLIC(QCoreApplication)

 

public:

    QCoreApplicationPrivate(int &aargc,  char **aargv);

    ~QCoreApplicationPrivate();

 

    bool sendThroughApplicationEventFilters(QObject *, QEvent *);

    bool sendThroughObjectEventFilters(QObject *, QEvent *);

    bool notify_helper(QObject *, QEvent *);

 

    virtual QString appName() const;

    virtual void createEventDispatcher();

    static void removePostedEvent(QEvent *);

#ifdef Q_OS_WIN

    static void removePostedTimerEvent(QObject *object, int timerId);

#endif

 

#ifdef Q_OS_MAC

    static QString macMenuBarName();

#endif

 

    static QThread *theMainThread;

    static QThread *mainThread();

    static bool checkInstance(const char *method);

    static void sendPostedEvents(QObject *receiver, int event_type, QThreadData *data);

 

#if !defined (QT_NO_DEBUG) || defined (QT_MAC_FRAMEWORK_BUILD) || defined (Q_OS_SYMBIAN)

    void checkReceiverThread(QObject *receiver);

#endif

    int &argc;

    char **argv;

    void appendApplicationPathToLibraryPaths(void);

 

#ifndef QT_NO_TRANSLATION

    QTranslatorList translators;

#endif

    uint application_type;

 

    QCoreApplication::EventFilter eventFilter;

 

    bool in_exec;

    bool aboutToQuitEmitted;

    QString cachedApplicationDirPath;

    QString cachedApplicationFilePath;

 

    static bool isTranslatorInstalled(QTranslator *translator);

 

    static QAbstractEventDispatcher *eventDispatcher;

    static bool is_app_running;

    static bool is_app_closing;

 

    static uint attribs;

    static inline bool testAttribute(uint flag) { return attribs & (1 << flag); }

};

该类才真正提供了事件机制的内部实现原理,提供了最主要的事件派送机制。

看来接下来要对Qt的事件派送机制进行详细的分析了。

那么我们从最熟悉的代码:exec()函数入手吧。

我们看到了对该方法的描述:

/*****************************************************************************

  Main event loop wrappers

 *****************************************************************************/

/*!

    Enters the main event loop and waits until exit() is called.

    Returns the value that was set to exit() (which is 0 if exit() is

    called via quit()).

 

    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.

 

    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 advanced idle processing schemes can

    be achieved using processEvents().

 

    We recommend that you connect clean-up code to the

    /l{QCoreApplication::}{aboutToQuit()} signal, instead of putting it in

    your application's /c{main()} function because on some platforms the

    QCoreApplication::exec() call may not return. For example, on Windows

    when the user logs off, the system terminates the process after Qt

    closes all top-level windows. Hence, there is no guarantee that the

    application will have time to exit its event loop and execute code at

    the end of the /c{main()} function after the QCoreApplication::exec()

    call.

 

    /sa quit(), exit(), processEvents(), QApplication::exec()

*/

在这得到的最主要提示是:我们最好将aboutToQuit信号与我们的清理代码相关联,在有些时候,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()->in_exec = false;

        if (!self->d_func()->aboutToQuitEmitted)

            emit self->aboutToQuit();

        self->d_func()->aboutToQuitEmitted = true;

        sendPostedEvents(0, QEvent::DeferredDelete);

    }

 

    return returnCode;

该函数首先做了一些条件的检测,对函数调用进行了一些限制,例如只能在主线程中调用该函数等。

接下来创建了QEventLoop类的对象,并调用该类的exec()方法。

看来我们要进入QEventLoop类看个究竟了。

该方面中的说明,比较有意义的应该是这一段了:

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().

在这里又一次看到了processEvents()方法,现在知道了,原来exec()方法的内部实现就是processEvents(),那么该方法可以执行大量运行时接收输入也就很正常了。现在需要看看该方法是如何做到时间的发送接收的:

Q_D(QEventLoop);

    if (!d->threadData->eventDispatcher)

        return false;

    if (flags & DeferredDeletion)

        QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);

    return d->threadData->eventDispatcher->processEvents(flags);

代码很少,前面是一些安全检测,接下来的两个关键函数是:

sendPostedEvents()processEvents()

void QCoreApplication::sendPostedEvents(QObject *receiver, int event_type)

{

    QThreadData *data = QThreadData::current();

 

    QCoreApplicationPrivate::sendPostedEvents(receiver, event_type, data);

}

跟踪到void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type, QThreadData *data)方法,发现这里是真正用于发送事件的地方,现在先不做深入研究。

继续往下看:

来自于QAbstractEventDispatcher类的

virtual bool processEvents(QEventLoop::ProcessEventsFlags flags) = 0;方法,我们需要找到其调用的子类。

记得我们曾经在分析QCoreApplication的时候,发现了该类的子类QEventDispatcherWin32,这就是我们真正调用的类了。

class Q_CORE_EXPORT QEventDispatcherWin32 : public QAbstractEventDispatcher

这样一来,我们可以看到,真正的底层实现,事件的与平台相关的部分就在这里了。不过今天研究不完了,我们明天再深入了解Win32平台下的事件派送类——QEventDispatcherWin32

20091027日星期二 2331

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值