Qt QObject 宏
成员变量
【const QMetaObject QObject::staticMetaObject】这个变量存储类的元对象。
- 元对象包含关于继承QObject的类的信息。
- 例如类名、超类名、属性、信号和插槽。
- 每个包含 Q_OBJECT 宏的类也将有一个元对象。
- 元对象信息是信号/槽连接机制和属性系统所需要的。inherits()函数也使用了元对象。
- 如果你有一个指向对象的指针,你可以使用 metaObject()来检索与该对象关联的元对象。
- 例子:
QPushButton::staticMetaObject.className(); // returns "QPushButton" QObject *obj = new QPushButton; obj->metaObject()->className(); // returns "QPushButton"
- 参考:metaObject().
相关的非成员变量
template <typename T> T qobject_cast(QObject *object) template <typename T> T qobject_cast(const QObject *object)
- 如果对象是T类型(或其子类),则返回转换为T类型的给定对象;否则返回nullptr。
- 如果object是nullptr,那么它也将返回nullptr。
- 类T必须(直接或间接)继承QObject,并使用Q_OBJECT 宏声明。
- 一个类被认为是继承了它自己。
QObject *obj = new QTimer; // QTimer inherits QObject QTimer *timer = qobject_cast<QTimer *>(obj); // timer == (QObject *)obj QAbstractButton *button = qobject_cast<QAbstractButton *>(obj); // button == nullptr
- object_cast()函数的行为类似于标准c++ dynamic_cast(),其优点是不需要RTTI支持,并且可以跨动态库边界工作。
- qobject_cast()也可以与接口一起使用; 详情请参阅 Plug & Paint 示例。
- 警告:如果T没有被 Q_OBJECT宏声明,这个函数的返回值是未定义的。
- 参考:QObject::inherits().
【typedef QObjectList】
template <typename T> QList<T> qFindChildren(const QObject *obj, const QRegExp ®Exp)
- 这个函数重载qFindChildren()。
- 个函数等价于obj->findChildren<T>(regExp)。
- 注意:这个函数是为msvc6提供的一个解决方案,它不支持成员模板函数。建议在新代码中使用其他形式。
- 参考:QObject::findChildren().
宏文档
【QT_NO_NARROWING_CONVERSIONS_IN_CONNECT】
- 当信号和槽使用基于PMF的语法连接时,定义这个宏将禁用信号携带的参数和槽接受的参数之间的收缩和浮点到整数的转换。
- 该函数是在Qt 5.8中引入的。
- 参考:QObject::connect.
【Q_CLASSINFO(Name, Value)】
- 这个宏将额外的信息关联到类,这可以通过QObject::metaObject()得到。
- Qt只在 Active Qt, Qt D-Bus 和Qt QML中有限地使用该特性。
- 额外的信息采用Name字符串和Value字面值字符串的形式。
- 示例:
class MyClass : public QObject { Q_OBJECT Q_CLASSINFO("Author", "Pierre Gendron") Q_CLASSINFO("URL", "http://www.my-organization.qc.ca") public: ... };
【Q_DISABLE_COPY(Class)】
- 禁用给定类的复制构造函数和赋值操作符。
- QObject的子类的实例不应该被认为是可以复制或赋值的值,而是作为唯一标识。
- 这意味着当您创建自己的QObject子类(director或indirect)时,不应该给它一个复制构造函数或赋值操作符。
- 但是,在类中简单地省略它们可能还不够,因为如果您错误地编写了一些需要复制构造函数或赋值操作符的代码(这很容易做到),编译器将精心地为您创建它。你必须做得更多。
- 好奇的用户会发现,从QObject派生出来的Qt类通常会把这个宏包含在私有部分中:
class MyClass : public QObject { private: Q_DISABLE_COPY(MyClass) };
- 它在private区段中声明了复制构造函数和赋值操作符,因此如果您错误地使用它们,编译器将报告错误。
class MyClass : public QObject { private: MyClass(const MyClass &) = delete; MyClass &operator=(const MyClass &) = delete; };
- 但即便如此,也未必能完全抓住每一个病例。你可能会想这样做:
QWidget w = QWidget();
- 首先,不要那样做。大多数编译器将生成使用复制构造函数的代码,因此将报告违反隐私的错误,但您的c++编译器不需要以特定的方式为该语句生成代码。
- 它既不能使用复制构造函数,也不能使用私有的赋值操作符生成代码。在这种情况下,不会报告任何错误,但是当您调用w的成员函数时,应用程序可能会崩溃。
- 参考:Q_DISABLE_COPY_MOVE 和Q_DISABLE_MOVE.
【Q_DISABLE_COPY_MOVE(Class)】
- 它禁止对给定类使用复制构造函数、赋值操作符、移动构造函数和移动赋值操作符,结合了Q_DISABLE_COPY 和Q_DISABLE_MOVE。
- 该函数是在Qt 5.13中引入的。
【Q_DISABLE_MOVE(Class)】
- 禁用给定Class的move构造函数和move赋值操作符。
- 该函数是在Qt 5.13中引入的。
- 参考:Q_DISABLE_COPY 和Q_DISABLE_COPY_MOVE。
【Q_EMIT】
- 使用此宏替换发出信号的emit关键字,当你想使用Qt信号和插槽 通过 3rd party signal/slot mechanism。
- 该宏通常在.pro文件中使用CONFIG变量指定no_keywords时使用,但即使没有指定no_keywords时也可以使用。
【Q_ENUM(...)】
class MyClass : public QObject { Q_OBJECT public: MyClass(QObject *parent = nullptr); ~MyClass(); enum Priority { High, Low, VeryHigh, VeryLow }; Q_ENUM(Priority) void setPriority(Priority priority); Priority priority() const; };
- 用Q_ENUM声明的枚举有 QMetaEnum在封闭的 QMetaObject 中注册。你也可以使用QMetaEnum::fromType()来获取QMetaEnum。
- 已注册枚举也自动注册到Qt元类型系统,使 QMetaType 知道它们,而不需要使用 Q_DECLARE_METATYPE()。
- 这将启用有用的功能; 例如,如果在QVariant中使用,您可以将它们转换为字符串。同样,将它们传递给QDebug将打印出它们的名称。
- 注意:在元对象系统中,枚举值是以signed int的形式存储的。
- 用int的有效值范围之外的值注册枚举将导致溢出,并在通过元对象系统访问它们时可能出现未定义的行为。
- 例如,QML通过元对象系统访问注册枚举。
- 该函数是在Qt 5.5中引入的。
- 参考: Qt's Property System.
【Q_ENUM_NS(...)】
- 这个宏在元对象系统中注册了enum类型。
- 它必须放在具有Q_NAMESPACE宏的命名空间的枚举声明之后。它与 Q_ENUM 相同,只是在命名空间中。
- 用Q_ENUM_NS声明的枚举在封闭的 QMetaObject中注册了QMetaEnum 。你也可以使用QMetaEnum::fromType()来获取QMetaEnum。
- 已注册枚举也自动注册到Qt元类型系统,使QMetaType知道它们,而不需要使用 Q_DECLARE_METATYPE()。
- 这将启用有用的功能;例如,如果在QVariant中使用,您可以将它们转换为字符串。同样,将它们传递给QDebug将打印出它们的名称。
- 注意:在元对象系统中,枚举值是以signed int的形式存储的。
- 用int的有效值范围之外的值注册枚举将导致溢出,并在通过元对象系统访问它们时可能出现未定义的行为。
- 例如,QML通过元对象系统访问注册枚举。
- 该函数是在Qt 5.8中引入的。
- 参考: Qt's Property System.
【Q_FLAG(...)】
- 这个宏向元对象系统注册一个单一的 flags type。它通常用于类定义中,声明给定枚举的值可以用作标志,并使用按位或运算符组合。对于名称空间,可以使用Q_FLAG_NS() 。
- 宏必须放在enum声明之后。flags类型的声明是使用 Q_DECLARE_FLAGS() 宏完成的。
- 例如,在QItemSelectionModel中, SelectionFlags标志以如下方式声明:
class QItemSelectionModel : public QObject { Q_OBJECT public: ... enum SelectionFlag { NoUpdate = 0x0000, Clear = 0x0001, Select = 0x0002, Deselect = 0x0004, Toggle = 0x0008, Current = 0x0010, Rows = 0x0020, Columns = 0x0040, SelectCurrent = Select | Current, ToggleCurrent = Toggle | Current, ClearAndSelect = Clear | Select }; Q_DECLARE_FLAGS(SelectionFlags, SelectionFlag) Q_FLAG(SelectionFlags) ... }
- 注意: Q_FLAG宏负责在元对象系统中注册单个标志值,所以除了这个宏之外,没有必要使用 Q_ENUM()。
- 该函数是在Qt 5.5中引入的。
- 参考: Qt's Property System.
【Q_FLAG_NS(...)】
- 这个宏向元对象系统注册一个单一的 flags type 。
- 在具有 Q_NAMESPACE宏的名称空间中使用它来声明给定枚举的值可以用作标志,并使用按位或运算符组合。
- 它与s Q_FLAG相同,但是在名称空间中。
- 宏必须放在enum声明之后。
- 注意 : Q_FLAG_NS宏负责在元对象系统中注册单个标志值,所以除了这个宏之外,没有必要使用Q_ENUM_NS()。
- 参考:该函数是在Qt 5.8中引入的。
- 参考: Qt's Property System.
【Q_GADGET】
- Q_GADGET宏是Q_OBJECT宏的轻版本,适用于那些不继承自QObject但仍然希望使用QMetaObject.提供的一些反射功能的类。
- 就像Q_OBJECT宏一样,它必须出现在类定义的私有部分中。
- Q_GADGET可以有 Q_ENUM, Q_PROPERTY 和Q_INVOKABLE,,但是它们不能有信号或槽。
- Q_GADGET使类成员staticMetaObject可用。staticMetaObject的类型是QMetaObject ,它提供对使用 Q_ENUMS声明的枚举的访问。
【Q_INTERFACES(...)】
- 这个宏告诉Qt类实现了哪些接口。这在实现插件时使用。
- 示例:
class BasicToolsPlugin : public QObject, public BrushInterface, public ShapeInterface, public FilterInterface { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.PlugAndPaint.BrushInterface" FILE "basictools.json") Q_INTERFACES(BrushInterface ShapeInterface FilterInterface) public: ... };
- 详细信息请参见 Plug & Paint Basic Tools 示例。
- 查看:Q_DECLARE_INTERFACE(), Q_PLUGIN_METADATA(), and How to Create Qt Plugins.
【Q_INVOKABLE】
- 将此宏应用于成员函数的声明,以允许它们通过元对象系统被调用。宏在返回类型之前写入,如下例所示:
class Window : public QWidget { Q_OBJECT public: Window(); void normalMethod(); Q_INVOKABLE void invokableMethod(); };
- invokableMethod()函数使用Q_INVOKABLE标记,使得它被注册到元对象系统中,并允许它被 QMetaObject::invokeMethod()调用。
- 因为normalMethod()函数没有以这种方式注册,所以不能使用 QMetaObject::invokeMethod()调用它。
- 如果一个可调用的成员函数返回一个指向QObject或QObject子类的指针,并且它是从QML调用的,则应用特殊的所有权规则。
- 有关更多信息,请参见 Data Type Conversion Between QML and C++。
【Q_NAMESPACE】
- Q_NAMESPACE宏可用于向名称空间添加 QMetaObject 功能。
- Q_NAMESPACEs可以有 Q_CLASSINFO, Q_ENUM_NS, Q_FLAG_NS,但不能有Q_ENUM, Q_FLAG, Q_PROPERTY, Q_INVOKABLE、signals和slot。
- Q_NAMESPACE使一个外部变量staticMetaObject可用。staticMetaObject的类型是 QMetaObject ,并提供对使用Q_ENUM_NS/Q_FLAG_NS.声明的枚举的访问。
- 例如:
namespace test { Q_NAMESPACE ...
- 该函数是在Qt 5.8中引入的。
- 参考:Q_NAMESPACE_EXPORT。
【Q_NAMESPACE_EXPORT(EXPORT_MACRO)】
- Q_NAMESPACE_EXPORT宏可用于向名称空间添加QMetaObject功能。
- 它的工作原理与Q_NAMESPACE宏完全一样。但是,在名称空间中定义的外部staticMetaObject变量是用提供的EXPORT_MACRO限定符声明的。
- 如果需要从动态库导出对象,这很有用。
- 例如:
namespace test { Q_NAMESPACE_EXPORT(EXPORT_MACRO) ...
- 该函数是在Qt 5.14中引入的。
- 参考: Q_NAMESPACE 和Creating Shared Libraries。
【Q_OBJECT】
- Q_OBJECT宏必须出现在类定义的私有部分,该私有部分声明自己的信号和槽,或者使用Qt的元对象系统提供的其他服务。
- 例如:
#include <QObject> class Counter : public QObject { Q_OBJECT public: Counter() { m_value = 0; } int value() const { return m_value; } public slots: void setValue(int value); signals: void valueChanged(int newValue); private: int m_value; };
- 注意: 这个宏要求类是QObject的子类。
- 使用Q_GADGET而不是Q_OBJECT来启用元对象系统对非QObject子类中的枚举的支持。
- 参考:Meta-Object System, Signals and Slots, 和Qt's Property System.
【Q_PROPERTY(...)】
- 这个宏用于在继承QObject的类中声明属性。属性的行为类似于类数据成员,但它们具有通过元对象系统( Meta-Object System)访问的附加特性。
Q_PROPERTY(type name (READ getFunction [WRITE setFunction] | MEMBER memberName [(READ getFunction | WRITE setFunction)]) [RESET resetFunction] [NOTIFY notifySignal] [REVISION int] [DESIGNABLE bool] [SCRIPTABLE bool] [STORED bool] [USER bool] [CONSTANT] [FINAL] [REQUIRED])
- 属性名、类型和READ函数是必需的。
- 该类型可以是QVariant支持的任何类型,也可以是用户定义的类型。
- 其他项是可选的,但WRITE函数是常见的。属性默认为true, USER默认为false。
- 示例:
Q_PROPERTY(QString title READ title WRITE setTitle USER true)
- 或者更多关于如何使用这个宏的细节,以及更详细的使用示例,请参阅Qt的属性系统( Qt's Property System)的讨论。
【Q_REVISION】
- 将此宏应用于成员函数的声明,以便在元对象系统中用修订号标记它们。宏在返回类型之前写入,如下例所示:
lass Window : public QWidget { Q_OBJECT Q_PROPERTY(int normalProperty READ normalProperty) Q_PROPERTY(int newProperty READ newProperty REVISION 1) public: Window(); int normalProperty(); int newProperty(); public slots: void normalMethod(); Q_REVISION(1) void newMethod(); };
- 当使用元对象系统向另一个API动态公开对象时,这很有用,因为您可以匹配其他API的多个版本所期望的版本。考虑以下简化的示例:
Window window; int expectedRevision = 0; const QMetaObject *windowMetaObject = window.metaObject(); for (int i=0; i < windowMetaObject->methodCount(); i++) if (windowMetaObject->method(i).revision() <= expectedRevision) exposeMethod(windowMetaObject->method(i)); for (int i=0; i < windowMetaObject->propertyCount(); i++) if (windowMetaObject->property(i).revision() <= expectedRevision) exposeProperty(windowMetaObject->property(i));
- 使用与前面示例相同的Window类,newProperty和newMethod只会在预期版本为1或更大时在此代码中公开。
- 因为如果没有标记,所有的方法都被认为是在修订0中,所以Q_REVISION(0)的标记是无效的并被忽略。
- 元对象系统本身不使用这个标记。目前,这只被QtQml模块使用。
- 有关更通用的字符串标记,请参见QMetaMethod::tag()。
- 参考: QMetaMethod::revision().
【Q_SET_OBJECT_NAME(Object)】
- 这个宏为Object指定objectName为“Object”。
- Object是否是一个指针并不重要,宏会自己计算出来。
- 该函数是在Qt 5.0中引入的。
- 参考:QObject::objectName()。
【Q_SIGNAL】
- 这是一个额外的宏,允许您将单个函数标记为信号。它可能非常有用,特别是当您使用第三方源代码解析器时,该解析器不理解信号或Q_SIGNALS组。
- 使用此宏替换类声明中的signals关键字,如果您想使用Qt signals和Slots 通过 3rd party signal/slot mechanism。
- 该宏通常在.pro文件中使用CONFIG变量指定no_keywords时使用,但即使没有指定no_keywords时也可以使用。
【Q_SIGNALS】
- 当你想用第三方信号/槽机制来使用Qt信号和槽时,使用这个宏来替换类声明中的signals关键字。
- 该宏通常在.pro文件中使用CONFIG变量指定no_keywords时使用,但即使没有指定no_keywords时也可以使用。
【Q_SLOT】
- 这是一个额外的宏,允许您将单个函数标记为插槽。它非常有用,特别是当您使用第三方源代码解析器时,该解析器不理解插槽或Q_SLOTS组。
- 使用此宏替换类声明中的signals关键字,如果您想使用Qt signals和Slots 通过 3rd party signal/slot mechanism。
- 该宏通常在.pro文件中使用CONFIG变量指定no_keywords时使用,但即使没有指定no_keywords时也可以使用。
【Q_SLOTS】
- 当你想用第三方信号/槽机制来使用Qt信号和槽时,使用这个宏来替换类声明中的slots关键字。
- 该宏通常在.pro文件中使用CONFIG变量指定no_keywords时使用,但即使没有指定no_keywords时也可以使用。