Skip to content

Commit 312277f

Browse files
Merge pull request #4 from Awesome-Embedded-Learning-Studio/feat/advanced_tutorials
feat: commit advanced tutorials for QtBase and QtGUI
2 parents 860602c + 37ecfcf commit 312277f

363 files changed

Lines changed: 15085 additions & 437 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
# AI helps
2-
AWESOMEQT_GUIDE.md
3-
.claude
2+
.claude/
3+
CLAUDE.md
44

55
reference/
66

77
# Build artifacts
88
build/
99
**/build/
1010

11+
# Python cache
12+
__pycache__/
13+
1114
# IDE / tooling cache
1215
.cache/
1316
**/.cache/

TODO.md

Lines changed: 42 additions & 255 deletions
Large diffs are not rendered by default.

codes_and_assets/instractions.md

Whitespace-only changes.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
build/
2+
*.user
3+
.idea/
4+
.vscode/
5+
CMakeCache.txt
6+
CMakeFiles/
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
cmake_minimum_required(VERSION 3.26) # Qt6 要求的最低 CMake 版本
2+
project(01-qobject-property-system-advanced LANGUAGES CXX) # 项目名与语言
3+
4+
set(CMAKE_CXX_STANDARD 17) # 统一 C++17
5+
set(CMAKE_CXX_STANDARD_REQUIRED ON) # 强制要求,不回退
6+
7+
set(CMAKE_AUTOMOC ON) # 自动运行 MOC,处理 Q_OBJECT
8+
set(CMAKE_AUTORCC ON) # 自动处理 .qrc 资源文件
9+
set(CMAKE_AUTOUIC ON) # 自动处理 .ui 文件(如有)
10+
11+
find_package(Qt6 REQUIRED COMPONENTS Core) # 按需添加模块
12+
13+
qt_add_executable(${PROJECT_NAME} # 生成可执行文件
14+
config_object.h # ConfigObject 类声明
15+
config_object.cpp # ConfigObject 类实现
16+
reflective_demo.h # 反射演示辅助函数声明
17+
reflective_demo.cpp # 反射演示辅助函数实现
18+
main.cpp # 程序入口
19+
)
20+
21+
target_link_libraries(${PROJECT_NAME}
22+
PRIVATE Qt6::Core # 按需链接
23+
)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/// @file config_object.cpp
2+
/// @brief ConfigObject 类实现——Q_PROPERTY 高级特性演示。
3+
///
4+
/// 对应教程:进阶层 01-QtBase/01-QObject 属性系统深度拆解。
5+
6+
#include "config_object.h"
7+
8+
ConfigObject::ConfigObject(QObject* parent)
9+
: QObject(parent)
10+
, m_appVersion(QStringLiteral("1.0.0"))
11+
, m_debugMode(false)
12+
, m_logLevel(kInfo)
13+
{
14+
}
15+
16+
QString ConfigObject::appVersion() const
17+
{
18+
return m_appVersion;
19+
}
20+
21+
bool ConfigObject::debugMode() const
22+
{
23+
return m_debugMode;
24+
}
25+
26+
void ConfigObject::setDebugMode(bool mode)
27+
{
28+
// 变更守卫:值没变就不赋值不发射信号
29+
// 这是 Q_PROPERTY 的黄金法则——防止无意义的信号发射
30+
if (m_debugMode == mode) {
31+
return;
32+
}
33+
m_debugMode = mode;
34+
emit debugModeChanged();
35+
}
36+
37+
void ConfigObject::resetDebugMode()
38+
{
39+
setDebugMode(false);
40+
}
41+
42+
int ConfigObject::logLevel() const
43+
{
44+
return m_logLevel;
45+
}
46+
47+
void ConfigObject::setLogLevel(int level)
48+
{
49+
// 范围检查 + 变更守卫
50+
if (level < kTrace) {
51+
level = kTrace;
52+
}
53+
if (level > kError) {
54+
level = kError;
55+
}
56+
if (m_logLevel == level) {
57+
return;
58+
}
59+
m_logLevel = level;
60+
emit logLevelChanged();
61+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/// @file config_object.h
2+
/// @brief 演示 Q_PROPERTY 高级特性:CONSTANT / RESET / FINAL / Q_ENUM。
3+
///
4+
/// 对应教程:进阶层 01-QtBase/01-QObject 属性系统深度拆解。
5+
6+
#pragma once
7+
8+
#include <QObject>
9+
#include <QString>
10+
11+
/// 演示 Q_PROPERTY 高级修饰符用法的配置对象。
12+
///
13+
/// 展示 CONSTANT(不可变属性)、RESET(恢复默认值)、
14+
/// FINAL(禁止子类覆盖)、Q_ENUM(枚举注册到元对象系统)等特性。
15+
class ConfigObject : public QObject
16+
{
17+
Q_OBJECT
18+
19+
// 元数据:可通过 metaObject()->classInfo() 在运行时读取
20+
Q_CLASSINFO("Author", "QtDemo")
21+
Q_CLASSINFO("Version", "2.0")
22+
23+
// CONSTANT 属性:只在构造时设置一次,不能有 WRITE 和 NOTIFY
24+
Q_PROPERTY(QString appVersion READ appVersion CONSTANT)
25+
26+
// 完整属性:READ / WRITE / NOTIFY / RESET 四件套
27+
// RESET 函数用于将属性恢复为默认值,常见于 Designer 的「重置属性」操作
28+
Q_PROPERTY(bool debugMode READ debugMode WRITE setDebugMode
29+
RESET resetDebugMode NOTIFY debugModeChanged)
30+
31+
// FINAL 属性:禁止子类用 Q_PROPERTY 覆盖
32+
// QML 引擎对 FINAL 属性可以做更激进的优化
33+
Q_PROPERTY(int logLevel READ logLevel WRITE setLogLevel
34+
NOTIFY logLevelChanged FINAL)
35+
36+
public:
37+
/// 日志级别枚举,通过 Q_ENUM 注册到元对象系统。
38+
enum LogLevel
39+
{
40+
kTrace = 0,
41+
kDebug = 1,
42+
kInfo = 2,
43+
kWarn = 3,
44+
kError = 4
45+
};
46+
Q_ENUM(LogLevel)
47+
48+
/// @brief 构造函数,初始化属性默认值。
49+
/// @param[in] parent 父对象指针,Qt 对象树自动管理生命周期。
50+
explicit ConfigObject(QObject* parent = nullptr);
51+
52+
/// @brief 获取应用程序版本号(CONSTANT 属性)。
53+
/// @return 版本号字符串。
54+
QString appVersion() const;
55+
56+
/// @brief 获取调试模式状态。
57+
/// @return true 表示调试模式已开启。
58+
bool debugMode() const;
59+
60+
/// @brief 设置调试模式。
61+
/// @param[in] mode 新的调试模式状态。
62+
void setDebugMode(bool mode);
63+
64+
/// @brief 将 debugMode 恢复为默认值 false。
65+
/// @note QMetaProperty::reset() 会调用这个函数。
66+
void resetDebugMode();
67+
68+
/// @brief 获取日志级别。
69+
/// @return 当前日志级别的整数值。
70+
int logLevel() const;
71+
72+
/// @brief 设置日志级别,自动裁剪到合法范围 [kTrace, kError]。
73+
/// @param[in] level 新的日志级别。
74+
void setLogLevel(int level);
75+
76+
signals:
77+
/// debugMode 属性变更通知信号。
78+
void debugModeChanged();
79+
80+
/// logLevel 属性变更通知信号。
81+
void logLevelChanged();
82+
83+
private:
84+
QString m_appVersion; // 应用版本号,CONSTANT,构造后不再变
85+
bool m_debugMode; // 调试模式开关
86+
int m_logLevel; // 当前日志级别
87+
};
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/// @file main.cpp
2+
/// @brief QObject 属性系统高级演示程序入口。
3+
///
4+
/// 演示 Q_PROPERTY 的 CONSTANT / RESET / FINAL 修饰符、
5+
/// setProperty() / property() 动态属性机制、
6+
/// QMetaObject / QMetaProperty 反射式属性枚举与能力检测。
7+
///
8+
/// 对应教程:进阶层 01-QtBase/01-QObject 属性系统深度拆解。
9+
10+
#include "config_object.h"
11+
#include "reflective_demo.h"
12+
13+
#include <QCoreApplication>
14+
#include <QDebug>
15+
#include <QMetaProperty>
16+
#include <QVariant>
17+
18+
int main(int argc, char* argv[])
19+
{
20+
QCoreApplication app(argc, argv);
21+
22+
// 演示 1: ConfigObject 基本属性操作——CONSTANT / RESET / FINAL
23+
qDebug() << "\n[演示 1] ConfigObject 属性基本操作";
24+
qDebug() << "----------------------------------------------";
25+
26+
ConfigObject config;
27+
28+
// CONSTANT 属性:只能在构造时设置,没有 WRITE 函数
29+
qDebug() << "appVersion (CONSTANT):" << config.appVersion();
30+
31+
// 尝试用 setProperty 写入 CONSTANT 属性——setProperty 会返回 false
32+
bool ok = config.setProperty("appVersion", QStringLiteral("2.0.0"));
33+
qDebug() << "setProperty(\"appVersion\", \"2.0.0\") 成功?" << ok;
34+
qDebug() << "appVersion 仍然是:" << config.appVersion();
35+
36+
// 带 RESET 的属性:resetDebugMode() 恢复默认值 false
37+
config.setDebugMode(true);
38+
qDebug() << "设置 debugMode = true, 当前值:" << config.debugMode();
39+
40+
// 通过 QMetaProperty::reset() 调用 RESET 函数
41+
const QMetaObject* metaObj = config.metaObject();
42+
int idx = metaObj->indexOfProperty("debugMode");
43+
if (idx >= 0) {
44+
QMetaProperty prop = metaObj->property(idx);
45+
prop.reset(&config);
46+
qDebug() << "调用 QMetaProperty::reset() 后, debugMode:"
47+
<< config.debugMode();
48+
}
49+
50+
// FINAL 属性:正常读写,但子类不能用 Q_PROPERTY 覆盖
51+
config.setLogLevel(ConfigObject::kDebug);
52+
qDebug() << "logLevel (FINAL):" << config.logLevel()
53+
<< ", 枚举名:"
54+
<< config.metaObject()
55+
->enumerator(
56+
config.metaObject()->indexOfEnumerator("LogLevel"))
57+
.valueToKey(config.logLevel());
58+
59+
qDebug() << "";
60+
61+
// 演示 2: setProperty() / property() 动态属性
62+
qDebug() << "\n[演示 2] 动态属性 setProperty() / property()";
63+
qDebug() << "----------------------------------------------";
64+
65+
ConfigObject obj;
66+
67+
// setProperty 对已声明的 Q_PROPERTY:调用 WRITE 函数
68+
obj.setProperty("debugMode", true);
69+
qDebug() << "setProperty(\"debugMode\", true) 后:" << obj.debugMode();
70+
71+
// setProperty 对未声明的名称:创建动态属性
72+
obj.setProperty("customTag", QStringLiteral("important"));
73+
obj.setProperty("internalFlags", 42);
74+
obj.setProperty("score", 95.5);
75+
76+
qDebug() << "动态属性 customTag:"
77+
<< obj.property("customTag").toString();
78+
qDebug() << "动态属性 internalFlags:"
79+
<< obj.property("internalFlags").toInt();
80+
qDebug() << "动态属性 score:"
81+
<< obj.property("score").toDouble();
82+
83+
// dynamicPropertyNames() 返回所有动态属性名称
84+
qDebug() << "动态属性列表:" << obj.dynamicPropertyNames();
85+
86+
// 访问不存在的属性返回无效 QVariant
87+
QVariant v = obj.property("nonExistent");
88+
qDebug() << "不存在的属性 isValid?" << v.isValid();
89+
90+
qDebug() << "";
91+
92+
// 演示 3: QMetaObject::propertyCount() / propertyOffset() 属性枚举
93+
qDebug() << "\n[演示 3] 属性枚举 propertyCount / propertyOffset";
94+
qDebug() << "----------------------------------------------";
95+
96+
printAllProperties(&config);
97+
printOwnProperties(&config);
98+
99+
// 演示 4: QMetaProperty 能力检测
100+
qDebug() << "\n[演示 4] QMetaProperty 能力检测";
101+
qDebug() << "----------------------------------------------";
102+
103+
checkPropertyCapabilities(&config);
104+
105+
// 演示 5: Q_CLASSINFO 元数据读取
106+
qDebug() << "\n[演示 5] Q_CLASSINFO 元数据";
107+
qDebug() << "----------------------------------------------";
108+
109+
printClassInfo(&config);
110+
111+
// 通过名称查找 classInfo
112+
const QMetaObject* mo = config.metaObject();
113+
int authorIdx = mo->indexOfClassInfo("Author");
114+
if (authorIdx >= 0) {
115+
qDebug() << "通过名称查找 classInfo(\"Author\"):"
116+
<< mo->classInfo(authorIdx).value();
117+
}
118+
119+
qDebug() << "";
120+
121+
// 总结
122+
qDebug() << "========================================";
123+
qDebug() << "属性系统高级演示结束";
124+
qDebug() << "要点回顾:";
125+
qDebug() << " 1. CONSTANT 属性不可写,无 WRITE 和 NOTIFY";
126+
qDebug() << " 2. RESET 函数用于恢复默认值";
127+
qDebug() << " 3. FINAL 属性禁止子类覆盖";
128+
qDebug() << " 4. setProperty() 对未声明属性创建动态属性";
129+
qDebug() << " 5. propertyOffset() 区分本类属性和继承属性";
130+
qDebug() << " 6. QMetaProperty 提供能力查询";
131+
qDebug() << " 7. Q_CLASSINFO 提供运行时元数据";
132+
qDebug() << "========================================";
133+
134+
return 0;
135+
}

0 commit comments

Comments
 (0)