QApplication是很常用的Qt类,随便创建一个带有QmainWindow项目就会自动创建QApplication对象,QApplication向上继承QGuiApplication,QGuiApplication向上继承QCoreApplication,QCoreApplication向上继承QObject,QObject再向上就没有了。
继承完QGuiApplication后引入一个Q_OBJECT宏,用Ctrl+鼠左进入是qobjectdefs.h,这个Q_OBJECT是在qapplication.h引入的头文件QtCore/qcoreapplication.h里#include <QtCore/qcoreapplication.h>,但又不是直接在qcoreapplication.h里,而是在qcoreapplication.h引入的头文件qobject.h里,qobject.h则直接引入了qobjectdefs.h。
class Q_WIDGETS_EXPORT QApplication : public QGuiApplication
{
Q_OBJECT
也就是说qobjectdefs.h被qobject.h引入,qobject.h被qcoreapplication.h引入,qcoreapplication.h被qapplication.h引用,所以这个Q_OBJECT是已经被定义的。回看QApplication的祖先,依次是QGuiApplication、QCoreApplication、乃至QObject本身都有一个Q_OBJECT,并且他们中Q_OBJECT宏都来自于qobjectdefs.h的定义。 那为什么不复用,由第一个引用qobjectdefs.h的qobject.h不断向下被继承,而是要在他的子类们不断的引入Q_OBJECT宏?因为Q_OBJECT宏没有被初始化,相当于在每次创建引入Q_OBJECT宏的类的对象的时候单独单独初始化了Q_OBJECT宏。从侧面反应了Qt的复用的前提是解耦合,如果不能解耦合宁可不复用
#define Q_OBJECT \
public: \ //公共
QT_WARNING_PUSH \ //qcompilerdetection.h中的宏,__pragma(warning(push))将当前警告等级压入栈中,来源于qcompilerdetection.h的引入头文件#include <QtCore/qobjectdefs_impl.h>↑#include <QtCore/qnamespace.h>↑#include <QtCore/qglobal.h>↑#include <QtCore/qcompilerdetection.h>
Q_OBJECT_NO_OVERRIDE_WARNING \ //定义是空的,没有启用元对象系统就不需要警告信息
static const QMetaObject staticMetaObject; \ //定义了一个名为staticMetaObject的静态常量,类型为QMetaObject
virtual const QMetaObject *metaObject() const; \ //定义了一个虚函数,返回值类型为const QMetaObject*
virtual void *qt_metacast(const char *); \ //定义了一个虚函数,参数为一个字符串指针
virtual int qt_metacall(QMetaObject::Call, int, void **); \ //定义了一个虚函数,参数为一个枚举类型和两个整数和一个指向void*的指针,其返回值为一个整数。该函数用于在运行时调用对象的成员函数,以支持信号槽机制等特性。
QT_TR_FUNCTIONS \ //用于定义翻译函数以便在多语言支持中使用。
private: \ //接下来是私有的
Q_OBJECT_NO_ATTRIBUTES_WARNING \ //定义是空的,没有启用元对象系统就不需要警告信息
Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \ //定义了一个静态函数,用于在运行时调用对象的静态成员函数,以支持元对象系统。Q_DECL_HIDDEN_STATIC_METACALL定义是空的,
QT_WARNING_POP \ //qcompilerdetection.h中QT_WARNING_POP宏定义为__pragma(warning(pop))将当前警告等级pop出栈,
struct QPrivateSignal {}; \ //定义了一个空结构体QPrivateSignal
QT_ANNOTATE_CLASS(qt_qobject, "") //QT_ANNOTATE_CLASS宏定义为(type, ...),(type, ...)(qt_qobject, "")注解一个类,qt_qobject是该类使用的标识符,空字符串""是附加信息
...
回看继承那一行
class Q_WIDGETS_EXPORT QApplication : public QGuiApplication
{ //Q_WIDGETS_EXPORT宏定义为__declspec(dllimport) 在qcompilerdetection.h中,
//class __declspec(dllimport) QApplication : public QGuiApplication表明在Windows平台上,QApplication 的定义是由某个动态链接库(DLL)中实现的,在程序运行时动态加载。
Q_OBJECT
那Q_OBJECT的故事暂且告一段落,目前只需知道他是定义了信号和槽,往下看下图QApplication,太多了,只说共性的问题, Q_PROPERTY
宏为QApplication
类定义了多个属性
Q_PROPERTY(QIcon windowIcon READ windowIcon WRITE setWindowIcon)
Q_PROPERTY(int cursorFlashTime READ cursorFlashTime WRITE setCursorFlashTime)
Q_PROPERTY(int doubleClickInterval READ doubleClickInterval WRITE setDoubleClickInterval)
Q_PROPERTY(int keyboardInputInterval READ keyboardInputInterval WRITE setKeyboardInputInterval)
#if QT_CONFIG(wheelevent)
Q_PROPERTY(int wheelScrollLines READ wheelScrollLines WRITE setWheelScrollLines)
#endif
#if QT_DEPRECATED_SINCE(5, 15)
Q_PROPERTY(QSize globalStrut READ globalStrut WRITE setGlobalStrut)
#endif
Q_PROPERTY(int startDragTime READ startDragTime WRITE setStartDragTime)
Q_PROPERTY(int startDragDistance READ startDragDistance WRITE setStartDragDistance)
#ifndef QT_NO_STYLE_STYLESHEET
Q_PROPERTY(QString styleSheet READ styleSheet WRITE setStyleSheet)
#endif
Q_PROPERTY(bool autoSipEnabled READ autoSipEnabled WRITE setAutoSipEnabled)
再往下看,太长了,只能计数了,需要的话自己去Ctrl+鼠左键配合ai去读代码。
public://公共,可用对象访问
#ifdef Q_QDOC //构造开始
QApplication(int &argc, char **argv);
#else
QApplication(int &argc, char **argv, int = ApplicationFlags);
#endif //构造结束
virtual ~QApplication();
static <class> <fun>; //伪代码,返回3个有关样式的方法
enum ColorSpec { NormalColor=0, CustomColor=1, ManyColor=2 };
#if QT_DEPRECATED_SINCE(5, 8) //不详开始
QT_DEPRECATED static int colorSpec();
QT_DEPRECATED static void setColorSpec(int);
#endif // QT_DEPRECATED_SINCE(5, 8)
#if QT_DEPRECATED_SINCE(5, 0)
QT_DEPRECATED static inline void setGraphicsSystem(const QString &) {}
#endif //不详结束
using QGuiApplication::palette;
static <class> <fun>(<ars>)//伪代码,3个静态方法
#if QT_VERSION < 0x060000 // remove these forwarders in Qt 6
static <class> <fun>(<ars>)//伪代码,2个静态方法
#endif
static QWidgetList allWidgets();//伪代码,12个静态方法
#if QT_DEPRECATED_SINCE(5, 0)
QT_DEPRECATED static inline void syncX() {}
#endif
static <class> <fun>(<ars>);//伪代码,20个静态方法
bool notify(QObject *, QEvent *) override;
... //一系列方法和其实现的条件
Q_SIGNALS: //信号
void focusChanged(QWidget *old, QWidget *now);
public: //第二个公共方法
QString styleSheet() const;
public Q_SLOTS:
#ifndef QT_NO_STYLE_STYLESHEET
void setStyleSheet(const QString& sheet);
#endif
void setAutoSipEnabled(const bool enabled);
bool autoSipEnabled() const;
static void closeAllWindows();
static void aboutQt();
protected: //protected方法2个
bool event(QEvent *) override;
bool compressEvent(QEvent *, QObject *receiver, QPostEventList *) override;
private: //私有方法,友元12个它们可以访问我的成员
Q_DISABLE_COPY(QApplication)
Q_DECLARE_PRIVATE(QApplication)
friend class QGraphicsWidget;
friend class QGraphicsItem;
friend class QGraphicsScene;
friend class QGraphicsScenePrivate;
friend class QWidget;
friend class QWidgetPrivate;
friend class QWidgetWindow;
friend class QTranslator;
friend class QWidgetAnimator;
#ifndef QT_NO_SHORTCUT
friend class QShortcut;
friend class QLineEdit;
friend class QWidgetTextControl;
#endif
friend class QAction;
#ifndef QT_NO_GESTURES
friend class QGestureManager;
#endif
};
QT_END_NAMESPACE
#endif // QAPPLICATION_H
结语,要搞清楚一个类,要从它的父类开始搞起,因为父类是成员最少的,同时,要不知道父类有什么却在子类中用到就会一头雾水,这是哪来的。但这也只是个思维框架,记不住所有成员,用的大概率是用的时候再去查。