Qt | One article summarizing QObject
1. Important knowledge of QObject
QObject
It is the core of Qt object model. The core feature of this model is a powerful seamless object communication mechanism, namely signals and slots . You can use to connect()
connect a signal to a slot function and disconnect()
destroy an existing connection using . To avoid a never-ending notification loop, blockSignals()
temporarily blocking signals can be used. Protected functions connectNotify()
and disconnectNotify()
can be used to trace signal connections.
In Qt QObject
, an "object tree" is formed based on the object. When created using another object as a parent object QObject
, the object will automatically add itself to children()
the list of parent objects. After the parent object takes ownership of the object, the child elements in the destructor will be automatically deleted. In development, you can use findChild()
or findChildren()
find sub-objects by name and optionally type.
Every object has one objectName()
, which can be found by corresponding metaObject()
its class name (function: QMetaObject::className()
). In actual development, you can use inherits()
functions to determine whether an object's class inherits QObject
another class in the inheritance hierarchy. When an object is deleted, destroyed()
a signal is emitted, which can be caught to avoid QObject
dangling references to it.
2. Important member functions of QObject
This section summarizes the member functions and important macro definitions commonly used in QObject during development.
1. Event acquisition and processing API
2. Thread association API of objects
3. Get sub-object API
4.qobject_cast
The function prototype is as follows:
Converts the given object to type T if the object is of type T (or a subclass); otherwise returns nullptr. If the object is nullptr, then it will also return nullptr.
NOTE: Class T must inherit (directly or indirectly)
QObject
and beQ_OBJECT
declared using macros.
qobject_cast()
The function behaves like standard C++ dynamic_cast()
, with the advantage that it does not require RTTI
(Run-Time Type Identification) support and can work across dynamic library boundaries .
5. Event processing related functions
6. Timer related functions
7. Important macro definitions
Q_DISABLE_COPY(Class) disables the use of copy constructors and assignment operators for a given class.
Q_DISABLE_COPY_MOVE(Class)
โ This macro is used to disable the copy constructor, assignment operator, move constructor and move assignment operator of a given class, grouping Q_DISABLE_COPY
and Q_DISABLE_MOVE
together.
Q_DISABLE_MOVE(Class 5.13)
Disallows the use of move constructors and move assignment operators for a given class.
Q_EMIT
When you want to use Qt signals and slots using a third-party signal/slot mechanism, you can use this macro instead of the emit
keyword to emit a signal.
Q_ENUM(...)
โ This macro is used to register an enumeration type with the meta-object system. The macro must be placed enum
after the declaration and in a class with the Q_OBJECT
or Q_GADGET
macro. For namespaces, should be used Q_ENUM_NS()
. For example:
Q_ENUM_NS(...)
โ This macro registers an enumeration type with the meta-object system. It must be placed enum
after the declaration, and Q_NAMESPACE
in the namespace of the macro. Same as Q_ENUM
, but in namespace.
Q_FLAG(...)
โ This macro registers a single-tagged type with the meta-object system. It is often used in class definitions to declare that a given enum
value can be used as a flag and combined using the bitwise OR operator. For namespaces, should be used Q_FLAG_NS()
. For example:
Q_INTERFACES(...)
โ This macro tells Qt which interfaces this class implements. Used when macro definition is implemented when plug-in is implemented. For example:
Q_NAMESPACE
Macros Q_NAMESPACE
are used to QMetaObject
add functionality to a namespace. Q_NAMESPACE
There can be Q_CLASSINFO
, Q_ENUM_NS
, Q_FLAG_NS, but there cannot be Q_ENUM
, Q_FLAG
, Q_PROPERTY
, Q_INVOKABLE
signal or slot functions.
Q_NAMESPACE_EXPORT(EXPORT_MACRO)
โ This macro works Q_NAMESPACE
exactly like the macro. However, external variables defined within the namespace are declared staticMetaObject
with the provided qualifier. EXPORT_MACRO
This macro definition is useful if you need to export objects from a dynamic library.
Q_OBJECT
The Q_OBJECT macro must appear in the private part of a class definition that declares its own signal and slot functions, or uses other support provided by the Qt meta-object system.
Q_PROPERTY(...)
โ This macro is used to QObject
declare properties in inherited classes. Properties behave like class data members, but they have additional properties that are accessible through the meta-object system. The following code:
Q_SIGNAL
โ This is an additional macro that allows us to mark individual functions as signals. Use this macro when using third-party source code parsers that do not support signals or Q_SIGNALS
groups.
Q_SLOT
โ This is an additional macro that allows individual functions to be marked as slot functions. Use this macro when using a third-party source code parser that does not support slot functions or Q_SLOT
groups.
3. Notes on the connection mechanism of signals and slots
1. [Automatic connection (default)] If the signal is issued in a thread that the receiving object has an association with, the behavior is the same as a direct connection. Otherwise, the behavior is the same as a queue connection.
2. [Direct connection] When the signal is sent, the slot function is called immediately. The slot function executes in the emitter's thread, which is not necessarily the receiver's thread.
3. [Queue connection] The slot is called when control returns to the event loop of the receiver thread, and the slot function is executed in the receiver's thread.
4. [Blocking queued connection] The slot is called as a queued connection, unless the current thread blocks until the slot function returns.
Note: Using this blocking queued connection type to connect objects in the same thread will cause a deadlock.
5. [Only connection] is the same as automatic connection, but the connection is only established without copying the existing connection. That is, if the same signal is already connected to the same slot for the same object, then no connection is created and connect()
returned false
.
The connection type can connect()
be specified by passing an additional parameter to . Note that if the event loop runs in the receiver's thread, it is unsafe to use a direct connection when the sender and receiver are in different threads, for the same reason that calling a function on an object located in another thread is unsafe same.
QObject::connect() itself is thread-safe.
For queue connections, the parameters passed must be types known to the Qt meta-object system, because Qt needs to copy parameters in order to store them; if the parameter types are not known to the Qt meta-object system, you will get an error message when using queue connections. At this time, you need to call qRegisterMetaType()
to register the data type with the meta-object system before creating the connection .
4. Thread correlation
In Qt, QObject instances have thread dependencies, or can be understood as QObject
existing in a certain thread. When a QObject receives a queued signal or published event, it is important that the slot function or event handler runs in the same thread as the object.
Note: If a QObject has no thread affinity (that is, if
thread()
0 is returned), or if it exists in a thread that is not running an event loop, then it cannot receive queued signals or published events.
By default, a QObject instance exists in the thread that created it. In actual development, you can use the thread()
thread association of the query object and moveToThread()
change the thread association of the object.
Note: All QObjects must live in the same thread as their parent object. In addition, you also need to know:
setParent()
(1) Will fail if the two QObjects involved are in different threads .
(2) When a QObject is moved to another thread, all its child threads will also be automatically moved.
moveToThread()
(3) Will fail if QObject has a parent object .
(4) If QObjects are QThread::run()
created in, they cannot become sub-objects of QThread objects, because QThread does not exist in the calling QThread::run()
thread.
setParent()
The parent-child relationship of a QObject must be set by passing a pointer to or calling the child constructor . Without this step, when moveToThread() is called, the object's member variables will remain in the old thread.
Last updated