Qt6 QML自定义组件、资源系统、模块化。
1. 模块化
项目文件本身就是一个模块
qt_add_qml_module(${PROJECT_NAME} # 默认导入项目的
URI QPlayer
VERSION 1.0
QML_FILES
main.qml
各模块路径是平级的,qmldir可以完全使用qt_add_qml_module代替,qt_add_qml_module更现代化,集中配置
1.1 模块内访问
同一模块内部:
qml组件名开头必须大写
方式零
导入的组件在同级目录,可以直接访问,不用导入
project/
├─ CMakeLists.txt
├─ A.qml
└─ B.qml
// A.qml内
B {
anchors.bottom: parent.bottom
}
方式一:相对路径导入(无 qmldir
)
📂 目录结构
project/
├─ CMakeLists.txt
├─ main.qml
└─ layout/
├─ Theme.qml
└─ BottomBar.qml
main.qml
import QtQuick
import "./layout" // 导入这个目录下的所有qml
Window {
width: 400
height: 300
visible: true
BottomBar { anchors.bottom: parent.bottom }
}
方式二:模块名导入(有 qmldir
)
一旦目录下存在 qmldir
,该目录就会被视为 独立模块,必须使用模块名导入。
📂 目录结构
project/
├─ CMakeLists.txt
├─ main.qml
└─ layout/
├─ qmldir
├─ Theme.qml
└─ BottomBar.qml
1) qmldir
写法
layout/qmldir
module MyApp.Layout
Theme 1.0 Theme.qml
BottomBar 1.0 BottomBar.qml
main.qml
import QtQuick
import MyApp.Layout 1.0
Window {
width: 400
height: 300
visible: true
BottomBar { anchors.bottom: parent.bottom }
}
2)qt_add_qml_module
等价写法
qt_add_qml_module(my_app
URI MyApp.Layout
VERSION 1.0
QML_FILES
layout/Theme.qml
layout/BottomBar.qml
)
效果完全等价,CMake 会自动生成 qmldir
。
1.2 模块间访问
项目可以有多个子模块,彼此之间通过模块名导入。
📂 目录结构
project/
├─ CMakeLists.txt
├─ main.qml
├─ layout/
│ ├─ Theme.qml
│ └─ BottomBar.qml
└─ controls/
└─ PlayButton.qml
1)qmldir
写法
layout/qmldir
module MyApp.Layout
Theme 1.0 Theme.qml
BottomBar 1.0 BottomBar.qml
controls/qmldir
module MyApp.Controls
PlayButton 1.0 PlayButton.qml
main.qml
import QtQuick
import MyApp.Layout 1.0
import MyApp.Controls 1.0
Window {
width: 400; height: 300; visible: true
BottomBar { anchors.bottom: parent.bottom }
PlayButton { anchors.centerIn: parent }
}
2)qt_add_qml_module
等价写法
qt_add_qml_module(my_app
URI MyApp.Layout
VERSION 1.0
QML_FILES
layout/Theme.qml
layout/BottomBar.qml
)
qt_add_qml_module(my_app
URI MyApp.Controls
VERSION 1.0
QML_FILES
controls/PlayButton.qml
)
单例的话模块内不用import或者用相对相对路径,可以直接用文件名访问属性
2. 模块打包方式
2.1 使用文件系统
开发阶段,QML 文件直接存在于磁盘,修改后立即生效。
qt_add_qml_module(my_app
URI MyApp
VERSION 1.0
QML_FILES
main.qml
layout/Theme.qml
layout/BottomBar.qml
)
运行时:
QQmlApplicationEngine engine;
engine.loadFromModule("MyApp", "Main");
图片、资源可用磁盘路径引用:
Image { source: "images/icon.png" }
2.2 使用 .qrc
资源打进二进制,跨平台一致。qt访问时,会当作一个文件系统,内部文件依然可以使用相对路径访问其他文件
resources.qrc
<RCC>
<qresource prefix="/MyApp">
<file>qml/Main.qml</file>
<file>qml/Component.qml</file>
<file>images/icon.png</file>
</qresource>
</RCC>
qt_add_qml_module(my_app
URI MyApp
VERSION 1.0
QML_FILES
qml/Main.qml
qml/Component.qml
RESOURCES
resources.qrc
)
使用:
import QtQuick
import MyApp 1.0
Window {
Component { MyComponent { } }
Image { source: "qrc:/MyApp/images/icon.png" }
}
3. QML 单例
3.1 C++ 注册单例
qmlRegisterSingletonType(QUrl("qrc:/MySingleton.qml"),
"MyApp.Singleton", 1, 0,
"MySingleton");
3.2 qmldir
+ pragma Singleton
📂 目录结构
project/
├─ CMakeLists.txt
├─ main.qml
└─ singletons/
└─ MySingleton.qml
MySingleton.qml
pragma Singleton
import QtQuick
QtObject {
property string appName: "My App"
}
1)qmldir
写法
singletons/qmldir
module MyApp.Singleton
singleton MySingleton 1.0 MySingleton.qml
main.qml
import QtQuick
import MyApp.Singleton 1.0
Window {
visible: true
Text { text: MySingleton.appName }
}
2)qt_add_qml_module
等价写法
# 标记为 QML 单例 要写在qt_add_qml_module 前
set_source_files_properties(singletons/MySingleton.qml
PROPERTIES QT_QML_SINGLETON_TYPE TRUE)
qt_add_qml_module(my_app
URI MyApp.Singleton
VERSION 1.0
QML_FILES
singletons/MySingleton.qml
)
QML 中仍然:
import MyApp.Singleton 1.0
Text { text: MySingleton.appName }
同模块的也需要 import自身模块来包含单例
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import QPlayer 1.0 // 自身模块
Rectangle{
// 使用ColumnLayout组织左侧边栏内容
ColumnLayout {
Text {
text: "左侧边栏"
font.pointSize: 20
color: Theme.currentTheme.fontColor // 单例组件属性
}
}
}
4. 动态加载组件
方法 1:Loader
Window {
Loader {
id: dynLoader
anchors.centerIn: parent
}
Button {
text: "Load"
onClicked: dynLoader.source = "MyComponent.qml"
}
}
方法 2:Component
+ createObject
Window {
Component {
id: myComp
MyComponent { }
}
Button {
text: "Create"
onClicked: myComp.createObject(parent, { "x": 100, "y": 100 })
}
}
📌 总结
- 无
qmldir
→ 可用相对路径导入。 - 有
qmldir
→ 必须用模块名导入。 - 现代 Qt 推荐用
qt_add_qml_module
,自动生成qmldir
。 - 资源打包 可用文件系统或
.qrc
,不影响模块语义。 - 单例 有两种方式:C++ 注册 /
qmldir
+pragma Singleton
。