核心功能基础
# 01.核心功能基础
# 目录介绍
- 1.1 基础类概念
- 1.1.1 对象模型
- 1.1.2 元对象系统
- 1.1.3 看个案例
- 1.2 QObject对象
- 1.2.1 QObject说明
- 1.2.2 树与父子关系
- 1.2.3 对象名称与查找
- 1.2.4 动态属性
- 1.2.5 信号与槽
- 1.2.6 事件处理
- 1.2.7 线程支持
- 1.2.8 注意事项
- 1.3 元对象系统
- 1.3.1 元对象说明
- 1.3.2 元对象编译器
- 1.3.3 反射(Reflection)
- 1.3.4 动态调用
- 1.4 关键宏与类
- 1.4.1 Q_OBJECT
- 1.4.2 QMetaObject
- 1.4.3 Q_PROPERTY
- 1.4.4 Q_INVOKABLE
- 1.4.5 总结一下
# 1.1 基础类概念
Qt Core 是 Qt 框架的基础模块,提供了跨平台的 C++ 核心功能,不依赖于 GUI 组件。
Qt 的对象模型和元对象系统是 Qt 框架的核心特性之一,它们为 Qt 提供了强大的功能,如信号与槽机制、动态属性、反射等。
# 1.1.1 对象模型
功能:提供对象树管理、父子关系、对象生命周期管理。核心类:
QObject:支持对象树和父子关系。所有 Qt 对象的基类,提供信号槽机制、对象树管理、事件处理等核心功能。QObject::parent()、QObject::children():访问父对象和子对象。
# 1.1.2 元对象系统
功能:提供运行时类型信息(RTTI)、信号与槽机制、动态属性系统等。核心类:
QObject:所有 Qt 对象的基类。QMetaObject:存储类的元信息(如类名、信号、槽、属性等)。QMetaMethod、QMetaProperty:用于访问方法和属性信息。- Q_GADGET:为非 QObject 类添加元对象能力
- Q_PROPERTY:声明属性系统
- Q_INVOKABLE:使方法可通过元对象系统调用
元对象系统,核心概念
- Qt 使用元对象系统实现信号与槽、动态属性、反射等功能。元对象系统通过 moc(元对象编译器)生成额外的代码,扩展 C++ 的功能。
关键特性
- Q_OBJECT 宏:在类声明中使用 Q_OBJECT 宏,启用元对象系统功能。
- 动态属性:可以在运行时为对象添加属性。
- 反射:可以在运行时获取对象的类名、方法、属性等信息。
# 1.1.3 看个案例
以下是一个简单的示例,展示了 Qt 对象模型和元对象系统的使用:
#include <QObject>
#include <QDebug>
class MyClass : public QObject {
Q_OBJECT // 启用元对象系统
Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged) //属性
public:
explicit MyClass(QObject *parent = nullptr) : QObject(parent), m_value(0) {} //构造方法
int value() const { return m_value; }
void setValue(int value) {
if (m_value != value) {
m_value = value;
emit valueChanged(m_value); //发送信号
}
}
signals: //信号
void valueChanged(int value);
private:
int m_value;
};
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
MyClass obj;
qDebug() << obj.metaObject()->className(); // 输出 "MyClass"
obj.setObjectName("MyObject");
// 使用元对象系统动态调用槽函数
QMetaObject::invokeMethod(&obj, "setValue", Q_ARG(int, 42));
// 使用反射获取属性
qDebug() << "Value:" << obj.property("value").toInt();
return app.exec();
}
#include "main.moc"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 1.2 QObject对象
# 1.2.1 QObject说明
QObject 是 Qt 框架中最基础的类,几乎所有 Qt 类都直接或间接继承自 QObject。
它提供了 Qt 对象模型的核心功能,如对象树管理、信号与槽机制、事件处理、动态属性等。
# 1.2.2 树与父子关系
对象树与父子关系:Qt 对象可以组织成树形结构,每个对象可以有一个父对象和多个子对象。
当父对象被销毁时,其所有子对象也会自动销毁。通过 QObject::setParent() 设置父对象,或通过 QObject::children() 获取子对象。
void setParent(QObject *parent);
QObject *parent() const;
2
# 1.2.3 对象名称与查找
每个 QObject 对象可以有一个唯一的名称(objectName),用于在对象树中查找。
使用 QObject::findChild() 或 QObject::findChildren() 查找对象。
QObject *findChild(const QString &name = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const;
QList<QObject *> findChildren(const QString &name = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const;
2
# 1.2.4 动态属性
Qt 对象可以动态添加属性,这些属性可以在运行时查询和修改。使用 QObject::setProperty() 设置属性,QObject::property() 获取属性。
bool setProperty(const char *name, const QVariant &value);
QVariant property(const char *name) const;
2
# 1.2.5 信号与槽
Qt 的信号与槽机制是对象模型的核心特性,用于对象之间的通信。
信号是事件的通知,槽是事件的响应函数。使用 QObject::connect() 连接信号与槽。
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection);
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method);
2
# 1.2.6 事件处理
QObject 提供了事件处理机制,可以重写 QObject::event() 或特定事件处理函数(如 QObject::timerEvent())来处理事件。
virtual bool event(QEvent *event);
virtual void timerEvent(QTimerEvent *event);
2
# 1.2.7 线程支持
QObject 可以在多线程中使用,但需要注意线程安全性。使用 QObject::moveToThread() 将对象移动到另一个线程。
void moveToThread(QThread *targetThread);
# 1.2.8 注意事项
Q_OBJECT宏: 所有使用信号与槽、动态属性等特性的类必须包含Q_OBJECT宏。- 对象树管理: 使用对象树管理父子关系,避免内存泄漏。注意不要在栈上创建带有父对象的
QObject,因为父对象销毁时会尝试删除子对象。 - 线程安全:
QObject默认是线程不安全的,跨线程操作时需要使用QMetaObject::invokeMethod()或信号与槽。 - 信号与槽: 信号与槽的参数类型必须完全匹配,否则连接会失败。使用
Qt::QueuedConnection实现跨线程的信号与槽连接。
# 1.3 元对象系统
元对象系统(Meta-Object System)是 Qt 实现对象模型的基础,它提供了以下功能:
# 1.3.1 元对象说明
每个 QObject 派生类都有一个对应的元对象,用于描述类的元信息(如类名、信号、槽、属性等)。
元对象由 moc(Meta-Object Compiler)生成,存储在 moc_*.cpp 文件中。
# 1.3.2 元对象编译器
moc 是 Qt 的工具,用于处理 Q_OBJECT 宏,生成元对象代码。在编译 Qt 项目时,moc 会自动处理包含 Q_OBJECT 宏的头文件。
# 1.3.3 反射(Reflection)
元对象系统支持反射,可以在运行时查询对象的类信息、信号、槽、属性等。使用 QMetaObject 类访问元对象信息。
# 1.3.4 动态调用
通过元对象系统,可以在运行时动态调用对象的信号、槽和属性。使用 QMetaObject::invokeMethod() 动态调用槽函数。
QMetaObject::invokeMethod 它通常用于跨线程调用、延迟执行或调用信号和槽。
函数原型
static bool QMetaObject::invokeMethod(
QObject *object, // 目标对象
const char *method, // 方法名
Qt::ConnectionType type, // 连接类型
QGenericReturnArgument ret, // 返回值
QGenericArgument val0 = QGenericArgument(), // 参数 1
QGenericArgument val1 = QGenericArgument(), // 参数 2
QGenericArgument val2 = QGenericArgument(), // 参数 3
QGenericArgument val3 = QGenericArgument(), // 参数 4
QGenericArgument val4 = QGenericArgument(), // 参数 5
QGenericArgument val5 = QGenericArgument(), // 参数 6
QGenericArgument val6 = QGenericArgument(), // 参数 7
QGenericArgument val7 = QGenericArgument(), // 参数 8
QGenericArgument val8 = QGenericArgument(), // 参数 9
QGenericArgument val9 = QGenericArgument() // 参数 10
);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
参数说明
object:目标对象,即调用方法的对象。method:方法名,可以是信号、槽或普通成员函数。方法名需要以字符串形式提供,例如"methodName"。type:连接类型,决定方法调用的方式。常用值:
Qt::AutoConnection:自动选择(默认)。Qt::DirectConnection:直接调用(同步)。Qt::QueuedConnection:队列调用(异步)。
ret:返回值,使用Q_RETURN_ARG宏定义。val0到val9:方法参数,使用Q_ARG宏定义。
看一个案例,比如:
QMetaObject::invokeMethod(this, [=]() { DoOnPalmServiceWorkingStatus(palm_working_enable); }, Qt::QueuedConnection);
- QMetaObject::invokeMethod:Qt 框架提供的函数,用于在对象上调用指定的方法。
- this:当前对象的指针,表示调用方法的对象。
- = { DoOnPalmServiceWorkingStatus(palm_working_enable); }:Lambda 函数,捕获当前作用域的变量(palm_working_enable),并调用 DoOnPalmServiceWorkingStatus 方法。
- Qt::QueuedConnection:指定调用方式为队列连接(异步调用),即方法会在事件循环中稍后执行,而不是立即执行。
# 1.4 关键宏与类
# 1.4.1 Q_OBJECT
Q_OBJECT 是一个宏,用于启用 Qt 的元对象系统功能,包括信号与槽机制、动态属性、对象树管理等。所有使用元对象系统的类必须包含 Q_OBJECT 宏。该宏会触发 moc 生成元对象代码。
- 启用信号与槽机制。
- 支持动态属性(
Q_PROPERTY)。 - 支持元对象信息(如
metaObject())。 - 支持对象树管理(如
parent()和children())。
注意事项
- 使用
Q_OBJECT的类必须继承自QObject。 - 如果使用
Q_OBJECT,必须运行moc(元对象编译器)生成额外的代码。
# 1.4.2 QMetaObject
QMetaObject 是 Qt 元对象系统的核心类,提供了对类元信息的访问。它的作用:
- 获取类的名称、父类、信号、槽、属性等信息。
- 动态调用方法或访问属性。
#include <QObject>
#include <QMetaObject>
#include <QDebug>
class MyClass : public QObject {
Q_OBJECT
public:
MyClass(QObject *parent = nullptr) : QObject(parent) {}
void doSomething() {
qDebug() << "Doing something...";
}
};
int main() {
MyClass obj;
// 获取元对象
const QMetaObject *meta = obj.metaObject();
// 获取类名
qDebug() << "Class name:" << meta->className();
// 获取父类名
qDebug() << "Parent class name:" << meta->superClass()->className();
return 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 1.4.3 Q_PROPERTY
Q_PROPERTY 是一个宏,用于声明类的属性,支持属性绑定、动画、序列化等功能。
作用
- 声明一个属性,并指定其读写方法、通知信号等。
- 支持在 QML 中绑定属性。
用法
#include <QObject>
#include <QDebug>
class MyClass : public QObject {
Q_OBJECT
Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged) // 声明属性
public:
MyClass(QObject *parent = nullptr) : QObject(parent), m_value(0) {}
int value() const { return m_value; } // 读方法
void setValue(int value) { // 写方法
if (m_value != value) {
m_value = value;
emit valueChanged(); // 发射通知信号
}
}
signals:
void valueChanged(); // 通知信号
private:
int m_value;
};
int main() {
MyClass obj;
// 使用属性
obj.setValue(42);
qDebug() << "Value:" << obj.value();
return 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
属性选项
READ:指定读方法。WRITE:指定写方法。NOTIFY:指定属性变化时的通知信号。RESET:指定重置方法。MEMBER:指定成员变量。CONSTANT:声明为常量属性。FINAL:禁止子类重写属性。
# 1.4.4 Q_INVOKABLE
Q_INVOKABLE 是一个宏,用于将方法标记为可通过元对象系统调用的方法。
作用:允许通过 QMetaObject::invokeMethod() 动态调用方法。支持在 QML 中调用方法。
1.跨线程调用,在 Qt 中,如果需要在非主线程中调用主线程的对象方法,可以使用 QMetaObject::invokeMethod 并指定 Qt::QueuedConnection。
QMetaObject::invokeMethod(
targetObject, // 目标对象
"methodName", // 方法名
Qt::QueuedConnection // 异步调用
);
2
3
4
5
2.延迟调用,通过 Qt::QueuedConnection,可以实现延迟调用。
QMetaObject::invokeMethod(
targetObject,
"methodName",
Qt::QueuedConnection
);
2
3
4
5
3.调用带参数的方法,如果方法需要参数,可以使用 Q_ARG 宏传递参数。
QMetaObject::invokeMethod(
targetObject,
"setValue",
Qt::AutoConnection,
Q_ARG(int, 42), // 参数 1
Q_ARG(QString, "Hello") // 参数 2
);
2
3
4
5
6
7
4.调用带返回值的方法,如果方法有返回值,可以使用 Q_RETURN_ARG 宏。
int result;
QMetaObject::invokeMethod(
targetObject,
"calculate",
Qt::DirectConnection,
Q_RETURN_ARG(int, result), // 返回值
Q_ARG(int, 10), // 参数 1
Q_ARG(int, 20) // 参数 2
);
qDebug() << "Result:" << result;
2
3
4
5
6
7
8
9
10
注意事项
Q_INVOKABLE方法可以是任意返回类型和参数类型。- 如果方法有返回值,可以使用
Q_RETURN_ARG获取返回值。
# 1.4.5 总结一下
Q_OBJECT:启用元对象系统功能。QMetaObject:提供对类元信息的访问。Q_PROPERTY:声明属性,支持绑定和通知。Q_INVOKABLE:标记方法为可通过元对象系统调用。