开源 C++ QT QML 开发(二)工程结构
开源 C++ QT QML 开发(二):工程结构详解
工程目录结构设计
典型的 QT QML 工程采用模块化目录结构,便于代码管理和维护。根目录通常包含以下子目录:
src/:存放核心 C++ 源码和 QML 文件include/:C++ 头文件resources/:QML 资源文件(如图片、字体)translations/:国际化文件tests/:单元测试代码
示例结构:
project/
├── CMakeLists.txt
├── src/
│ ├── main.cpp
│ ├── qml/
│ │ └── MainWindow.qml
│ └── backend/
│ └── AppCore.cpp
├── include/
│ └── backend/
│ └── AppCore.h
└── resources/
└── images/
└── logo.png
CMake 构建系统配置
现代 QT 项目推荐使用 CMake 作为构建系统。基础配置需包含 QT 模块声明和资源文件注册:
cmake_minimum_required(VERSION 3.16)
project(DemoApp LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
find_package(Qt6 REQUIRED COMPONENTS Quick Widgets)
qt_add_executable(DemoApp
src/main.cpp
src/backend/AppCore.cpp
)
qt_add_qml_module(DemoApp
URI com.example.DemoApp
VERSION 1.0
QML_FILES src/qml/MainWindow.qml
)
target_link_libraries(DemoApp
Qt6::Quick
Qt6::Widgets
)
QML 与 C++ 交互架构
实现高效的前后端交互需要建立明确的接口层:
- 在 C++ 中注册 QML 类型:
// AppCore.h
#include <QObject>
#include <QtQml/qqml.h>
class AppCore : public QObject {
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(QString version READ version CONSTANT)
public:
explicit AppCore(QObject *parent = nullptr);
QString version() const;
};
- 在 QML 中调用 C++ 功能:
// MainWindow.qml
import QtQuick 2.15
import com.example.DemoApp 1.0
Rectangle {
property AppCore core: AppCore {}
Text {
text: core.version
}
}
资源管理系统
QT 资源系统(.qrc)用于打包各类静态文件:
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>resources/images/logo.png</file>
<file>src/qml/MainWindow.qml</file>
</qresource>
</RCC>
在 QML 中通过统一路径访问:
Image {
source: "qrc:/images/logo.png"
}
多平台构建策略
通过条件编译处理平台差异:
if(ANDROID)
qt_add_android_apk(DemoApp)
elseif(IOS)
qt_add_ios_bundle(DemoApp)
else()
qt_add_executable(DemoApp ...)
endif()
持续集成配置
示例 GitHub Actions 配置:
name: CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: sudo apt-get install qt6-base-dev
- run: |
mkdir build
cd build
cmake ..
make
性能优化技巧
- 异步加载重型组件:
Loader {
source: "HeavyComponent.qml"
asynchronous: true
}
- 使用绑定优化:
Text {
text: Qt.binding(() => model.data[index].name)
}
- C++ 端实现数据缓存:
QVariant AppCore::getCachedData() {
if(m_cache.isNull()) {
m_cache = fetchDataFromNetwork();
}
return m_cache;
}
调试与日志系统
集成 qDebug 和 QML 控制台输出:
qInstallMessageHandler([](QtMsgType type, const QMessageLogContext &context, const QString &msg) {
QByteArray localMsg = msg.toLocal8Bit();
fprintf(stderr, "[%s] %s\n", qPrintable(QDateTime::currentDateTime().toString()), localMsg.constData());
});
在 QML 中使用调试工具:
Console {
id: debugConsole
function log(msg) {
print("[DEBUG]", msg)
}
}
BbS.okacop092.info/PoSt/1120_127366.HtM
BbS.okacop093.info/PoSt/1120_484356.HtM
BbS.okacop094.info/PoSt/1120_229054.HtM
BbS.okacop095.info/PoSt/1120_790585.HtM
BbS.okacop096.info/PoSt/1120_387524.HtM
BbS.okacop097.info/PoSt/1120_009554.HtM
BbS.okacop098.info/PoSt/1120_488346.HtM
BbS.okacop099.info/PoSt/1120_852221.HtM
BbS.okacop114.info/PoSt/1120_285054.HtM
BbS.okacop829.info/PoSt/1120_944614.HtM
BbS.okacop092.info/PoSt/1120_770904.HtM
BbS.okacop093.info/PoSt/1120_162227.HtM
BbS.okacop094.info/PoSt/1120_486237.HtM
BbS.okacop095.info/PoSt/1120_706922.HtM
BbS.okacop096.info/PoSt/1120_482784.HtM
BbS.okacop097.info/PoSt/1120_227569.HtM
BbS.okacop098.info/PoSt/1120_870925.HtM
BbS.okacop099.info/PoSt/1120_269727.HtM
BbS.okacop114.info/PoSt/1120_062567.HtM
BbS.okacop829.info/PoSt/1120_781006.HtM
BbS.okacop092.info/PoSt/1120_482109.HtM
BbS.okacop093.info/PoSt/1120_953354.HtM
BbS.okacop094.info/PoSt/1120_427230.HtM
BbS.okacop095.info/PoSt/1120_941729.HtM
BbS.okacop096.info/PoSt/1120_457030.HtM
BbS.okacop097.info/PoSt/1120_589226.HtM
BbS.okacop098.info/PoSt/1120_771174.HtM
BbS.okacop099.info/PoSt/1120_532068.HtM
BbS.okacop114.info/PoSt/1120_174166.HtM
BbS.okacop829.info/PoSt/1120_080474.HtM
BbS.okacop092.info/PoSt/1120_815511.HtM
BbS.okacop093.info/PoSt/1120_951544.HtM
BbS.okacop094.info/PoSt/1120_590092.HtM
BbS.okacop095.info/PoSt/1120_321159.HtM
BbS.okacop096.info/PoSt/1120_024120.HtM
BbS.okacop097.info/PoSt/1120_806906.HtM
BbS.okacop098.info/PoSt/1120_699246.HtM
BbS.okacop099.info/PoSt/1120_050461.HtM
BbS.okacop114.info/PoSt/1120_637159.HtM
BbS.okacop829.info/PoSt/1120_461076.HtM
BbS.okacop092.info/PoSt/1120_434403.HtM
BbS.okacop093.info/PoSt/1120_418774.HtM
BbS.okacop094.info/PoSt/1120_647458.HtM
BbS.okacop095.info/PoSt/1120_047638.HtM
BbS.okacop096.info/PoSt/1120_249754.HtM
BbS.okacop097.info/PoSt/1120_987490.HtM
BbS.okacop098.info/PoSt/1120_422986.HtM
BbS.okacop099.info/PoSt/1120_238471.HtM
BbS.okacop114.info/PoSt/1120_369663.HtM
BbS.okacop829.info/PoSt/1120_098147.HtM
BbS.okacop000.info/PoSt/1120_161509.HtM
BbS.okacop001.info/PoSt/1120_272113.HtM
BbS.okacop002.info/PoSt/1120_144783.HtM
BbS.okacop003.info/PoSt/1120_429379.HtM
BbS.okacop004.info/PoSt/1120_732060.HtM
BbS.okacop005.info/PoSt/1120_183306.HtM
BbS.okacop006.info/PoSt/1120_652975.HtM
BbS.okacop007.info/PoSt/1120_573708.HtM
BbS.okacop008.info/PoSt/1120_248302.HtM
BbS.okacop009.info/PoSt/1120_925896.HtM
BbS.okacop000.info/PoSt/1120_044029.HtM
BbS.okacop001.info/PoSt/1120_859181.HtM
BbS.okacop002.info/PoSt/1120_504285.HtM
BbS.okacop003.info/PoSt/1120_729639.HtM
BbS.okacop004.info/PoSt/1120_594416.HtM
BbS.okacop005.info/PoSt/1120_002494.HtM
BbS.okacop006.info/PoSt/1120_672798.HtM
BbS.okacop007.info/PoSt/1120_228720.HtM
BbS.okacop008.info/PoSt/1120_223698.HtM
BbS.okacop009.info/PoSt/1120_853315.HtM
BbS.okacop000.info/PoSt/1120_540217.HtM
BbS.okacop001.info/PoSt/1120_655666.HtM
BbS.okacop002.info/PoSt/1120_958830.HtM
BbS.okacop003.info/PoSt/1120_237132.HtM
BbS.okacop004.info/PoSt/1120_878788.HtM
BbS.okacop005.info/PoSt/1120_479141.HtM
BbS.okacop006.info/PoSt/1120_544147.HtM
BbS.okacop007.info/PoSt/1120_595161.HtM
BbS.okacop008.info/PoSt/1120_608021.HtM
BbS.okacop009.info/PoSt/1120_237504.HtM
查看18道真题和解析