——加载与状态监控)
目录1. 引言2. 演示效果3. 代码说明3.1 从文件加载组件3.2 加载 Component 组件3.3 加载状态监控3.4 动态标签页4. 技术要点4.1 source vs sourceComponent4.2 Loader 常用属性与信号4.3 访问加载的组件4.4 常见问题5. 工程下载1. 引言QML 的 Loader 组件是一种轻量级的容器可以加载来自文件或 Component 定义的 UI 元素。它支持异步加载、状态监控、动态切换等功能广泛应用于标签页切换、延迟加载、动态控件创建等场景。本文是 QML Loader 示例合集的上篇 基于历史示例进行优化:QML Loader加载组件与状态监控QML Loader动态加载与控件创建展示了 Loader 的加载方式与状态监控。由于代码篇幅较长文章中只显示关键部分完整代码见下载链接。2. 演示效果项目中的 Main.qml 文件使用 Flow 布局展示了 Loader 的不同使用方式以下为上篇涉及的四个示例从文件加载组件通过 source 属性加载外部 QML 文件加载 Component 组件通过 sourceComponent 属性加载内联定义的 Component加载状态监控监控 Loader 的 status 变化处理加载成功、失败等状态动态标签页模拟多页面切换动态加载不同页面内容3. 代码说明3.1 从文件加载组件文件Demo_LoaderFile.qml运行效果从文件加载组件是 Loader 最基础的用法通过设置 source 属性指向一个外部 QML 文件路径。关键代码BaseRect { ColumnLayout { anchors.fill: parent anchors.margins: 15 spacing: 10 Text { text: 1. 从文件加载组件 font.pointSize: 13 font.bold: true } RowLayout { Layout.fillWidth: true spacing: 10 Button { text: 加载组件 onClicked: loader.source component/MyComponent.qml } Button { text: 卸载组件 onClicked: loader.source } } Rectangle { Layout.fillWidth: true Layout.fillHeight: true color: Qt.rgba(0.95, 0.95, 0.95, 1) radius: 4 Loader { id: loader anchors.fill: parent anchors.margins: 10 } Text { anchors.centerIn: parent text: loader.status Loader.Ready ? : 点击「加载组件」 font.pointSize: 11 color: #999 visible: loader.status ! Loader.Ready } } } }代码说明通过设置source属性加载外部 QML 文件将 source 设置为空字符串可以卸载当前组件并释放内存。要点source支持相对路径和绝对路径也支持 URL将source设置为空字符串可以卸载组件使用loader.status可以判断加载状态使用visible属性可以显示占位提示文本引用文件未展示component/MyComponent.qml3.2 加载 Component 组件文件Demo_LoaderComponent.qml运行效果Component 是内联定义的组件模板通过sourceComponent属性加载适用于组件结构简单且不需要复用外部文件的场景。关键代码BaseRect { Component { id: com1 Rectangle { width: 100 height: 100 color: #3498db radius: 6 Text { anchors.centerIn: parent text: Component color: #fff font.pointSize: 12 } } } ColumnLayout { anchors.fill: parent anchors.margins: 15 spacing: 10 Text { text: 2. 加载 Component 组件 font.pointSize: 13 font.bold: true } RowLayout { Layout.fillWidth: true spacing: 10 Button { text: 加载 onClicked: loader.sourceComponent com1 } Button { text: 卸载 onClicked: loader.sourceComponent null } } Rectangle { Layout.fillWidth: true Layout.fillHeight: true color: Qt.rgba(0.95, 0.95, 0.95, 1) radius: 4 Loader { id: loader anchors.fill: parent anchors.margins: 10 } Text { anchors.centerIn: parent text: loader.item ? : 点击「加载」 font.pointSize: 11 color: #999 visible: !loader.item } } } }代码说明通过sourceComponent属性加载内联定义的 Component将属性设为 null 即可卸载组件。要点sourceComponent用于加载内联定义的 Component 对象将sourceComponent设置为null可以卸载组件source和sourceComponent互斥同时设置会导致冲突Component 是模板定义不会立即创建实例只有在被 Loader 加载时才会实例化3.3 加载状态监控文件Demo_LoaderStatus.qml运行效果加载状态监控展示了 Loader 的status属性和onStatusChanged信号可以处理加载成功、失败等不同状态。关键代码BaseRect { ColumnLayout { anchors.fill: parent anchors.margins: 15 spacing: 10 Text { text: 3. 加载状态 font.pointSize: 13 font.bold: true } RowLayout { Layout.fillWidth: true spacing: 10 Button { text: 加载有效组件 onClicked: loader.source component/ExistingComponent.qml } Button { text: 加载无效组件 onClicked: loader.source component/NonExistentComponent.qml } } Rectangle { Layout.fillWidth: true Layout.fillHeight: true color: Qt.rgba(0.95, 0.95, 0.95, 1) radius: 4 Loader { id: loader anchors.fill: parent anchors.margins: 10 onStatusChanged: { if (status Loader.Error) { statusText.color #e74c3c } else if (status Loader.Ready) { statusText.color #2ecc71 } else { statusText.color #333 } } } } Text { id: statusText Layout.fillWidth: true text: { switch (loader.status) { case Loader.Null: return 组件未加载 case Loader.Loading: return 正在加载... case Loader.Ready: return 加载完成 case Loader.Error: return 加载错误无效组件 default: return } } font.pointSize: 11 color: #333 } } }代码说明通过监听onStatusChanged信号处理加载状态变化使用status属性判断当前状态并显示对应的提示信息。状态枚举状态说明触发条件Null未设置组件初始化状态Loading正在加载组件正在加载中Ready加载完成组件成功加载Error加载错误文件不存在或解析失败要点status是只读属性反映 Loader 的当前加载状态onStatusChanged信号在状态改变时触发加载失败时可以通过状态变化显示错误提示或占位图引用文件未展示component/ExistingComponent.qml、component/NonExistentComponent.qml不存在用于演示错误状态3.4 动态标签页文件Demo_LoaderDynamicTab.qml运行效果动态标签页展示了 Loader 在多页面切换中的应用通过切换 source 属性实现不同页面的按需加载。关键代码BaseRect { ColumnLayout { anchors.fill: parent anchors.margins: 15 spacing: 10 Text { text: 4. 动态标签页 font.pointSize: 13 font.bold: true } RowLayout { Layout.fillWidth: true spacing: 10 Button { text: 页面1 onClicked: loader.source component/Page1.qml } Button { text: 页面2 onClicked: loader.source component/Page2.qml } Button { text: 页面3 onClicked: loader.source component/Page3.qml } } Rectangle { Layout.fillWidth: true Layout.fillHeight: true color: Qt.rgba(0.95, 0.95, 0.95, 1) radius: 4 Loader { id: loader anchors.fill: parent anchors.margins: 10 } } Text { text: 当前: (loader.source ? loader.source.toString().split(/).pop() : 无) font.pointSize: 11 color: #666 } } }代码说明通过切换不同的 source 实现页面切换Loader 会自动销毁旧页面并加载新页面只保留当前页面在内存中节省资源。要点切换 source 时Loader 会自动销毁旧组件并加载新组件旧组件会被完全销毁状态不会保留适用于需要节省内存的标签页、导航页面等场景可以通过loader.source.toString()获取当前加载的文件路径引用文件未展示component/Page1.qml、component/Page2.qml、component/Page3.qml4. 技术要点4.1 source vs sourceComponent两种加载方式的选择特性sourcesourceComponent来源外部 QML 文件内联定义的 Component适用场景大型组件、可复用组件简单组件、一次性组件卸载方式设置为设置为null异步加载支持asynchronous: true不支持Component 已在内存中内存占用按需加载节省内存组件定义始终在内存中典型场景标签页、对话框、复杂视图弹窗内容、简单状态切换注意事项source和sourceComponent互斥同时设置会导致未定义行为当source和sourceComponent都为空时Loader 不加载任何内容4.2 Loader 常用属性与信号Loader 常用属性Loader { source: url // 外部 QML 文件路径 sourceComponent: Component // 内联 Component 对象 active: bool // 是否激活加载 asynchronous: bool // 是否异步加载仅 source item: Item // 加载的组件实例只读 status: enum // 加载状态只读 progress: real // 加载进度 0.0-1.0只读 }状态枚举Loader.Null // 未设置组件 Loader.Loading // 正在加载 Loader.Ready // 加载完成 Loader.Error // 加载失败常用信号onLoaded: { ... } // 加载完成时触发 onStatusChanged: { ... } // 状态改变时触发 onProgressChanged: { ... } // 加载进度改变时触发4.3 访问加载的组件Loader 加载完成后可以通过loader.item访问加载的组件实例从而读取或修改其属性。Loader { id: loader source: MyComponent.qml onLoaded: { item.myProperty value item.myMethod() } }要点loader.item在组件未加载时为 null访问loader.item前应先检查是否非空只能访问加载组件中声明为property的属性可以通过属性绑定实现动态更新4.4 常见问题Q1如何异步加载大组件设置asynchronous: true可以在后台线程加载组件避免阻塞主线程Loader { source: LargeComponent.qml asynchronous: true }Q2Loader 卸载组件时会自动销毁吗是的当切换 source 或 sourceComponent 时Loader 会自动销毁旧组件并释放内存。5. 工程下载下载链接QML Loader 组件示例合集