好消息,2026年3.31日,QT官方正式发布鸿蒙版QT。本次开源发布正式推出面向鸿蒙系统平板和PC设备的Qt 5.12.12 LTS 适配版本,在完整保留 Qt 5.12.12 核心能力(含界面渲染、信号槽机制、跨平台 I/O、网络通信及数据库模块)的基础上,深度适配鸿蒙系统架构。本版本可降低开发者跨平台移植成本,加速 Qt 与鸿蒙生态融合,助力多场景鸿蒙应用高效开发。
QT官方鸿蒙版开源地址 :https://wiki.qt.io/Qt5.12.12_Open_Source_Release_for_HarmonyOS_zh
QT官方文档地址 :https://wiki.qt.io/Qt_for_OpenHarmony/zh

前言
在 HarmonyOS 上运行 Qt 应用,跟传统的PC上的QT应用不同。
传统的PC上的QT应用是使用QtCreator开发完成后,直接编译为可执行文件exe.。 而鸿蒙版QT的开发流程,则是使用鸿蒙版QT的SDK和qmake工具链,最终的编译产物为.so. 之后呢还需要鸿蒙的QT工程项目模版,把so加载进去,将应用编译打包为hap或app包。
在HarmonyOS 上运行 Qt 应用,通常需要三层协作:系统 Ability 与窗口 、ArkUI 中的原生节点(XComponent) ,以及 Qt 平台的 QPA 插件(本模板中为 libqohos.so) 。当产品希望在「不整页跳转」的前提下,把 Qt 界面嵌进另一个界面的指定区域时,系统提供了 EmbeddedUIExtensionAbility(嵌入式 UI 扩展能力) :由宿主页面的 EmbeddedComponent 发起一次嵌入会话,扩展侧在独立能力中加载页面并完成绘制与交互。
本文以鸿蒙项目模版,仓库内 ohostemplateforqtapplication_20260331 为例,介绍下QT项目结构运行原理与 EmbeddedUIExtensionAbility。
ohostemplateforqtapplication是用于构建最终 OpenHarmony Qt 应用程序的 DevEco 项目模板。这将用于在 HarmonyOS 设备上运行 Qt 应用程序。 开发者也可以从以下链接获取最新项目工程模版: http://codereview.qtcompany.cn:29416/template/
从 应用级 app.json5、工程级 build-profile.json5、模块级 module.json5 到 ArkTS 与原生库调用关系 ,说明模板工程的运行原理,并单独梳理 EmbeddedUIExtensionAbility 在本项目中的职责与数据流。文中代码与配置均来自当前仓库快照;系统 API 行为以你所使用的 HarmonyOS SDK 版本及官方文档为准。
1. 核心概念
1.1 Qt 在鸿蒙模板中的位置
- 入口形态 :模板将 主界面 实现为
UIAbility子类QAbility,生命周期各阶段委托给libqohos.so暴露的 NAPI(代码中以import qpa from 'libqohos.so'引用),由 Qt for OpenHarmony / HarmonyOS 的 QPA 与系统窗口、输入等对接。 - 绘制落点 :ArkUI 页面通过
XComponent,type: XComponentType.NODE,libraryname: 'qohos'创建原生节点;QPA 在该节点上挂载 Qt 的渲染与事件循环逻辑。主窗口与嵌入扩展会话各对应一套页面与节点,但共用同一套qohos原生模块名。 - 业务库 :实际运行的 Qt 可执行形态为共享库(如
libcalculator.so),名称在QtAppConstants.ets的APP_LIBRARY_NAME中配置,并需与entry/libs/<ABI>/下放置的.so一致。
1.2 EmbeddedUIExtensionAbility 在本项目中的角色
- 系统定义 :
EmbeddedUIExtensionAbility是嵌入式 UI 类扩展能力,与 UIExtension 会话(UIExtensionContentSession) 绑定;每次嵌入对应一次会话创建与销毁。 - 模板封装 :
QBaseEmbeddedUiExtensionAbility继承系统基类,在onCreate、onSessionCreate、onSessionDestroy、onDestroy中统一转发到qpa.handleQEmbeddedUiExtensionAbility*;并在首次创建时用uiExtensionMode: true初始化 Qt 应用上下文,使 QPA 按「扩展嵌入」路径而非普通全屏 Ability 路径工作。 - 双扩展名 :
module.json5声明了两个嵌入式扩展:QEmbeddedUiExtensionAbility(extensionProcessMode: "instance")与QBundledEmbeddedUiExtensionAbility(extensionProcessMode: "bundle"),便于在同一模板内对比或选用不同进程/打包语义(具体调度以系统实现为准)。
1.3 宿主侧 EmbeddedComponent
- 使用位置 :模板在 feature 模块
qEmbeddedUiExtensionHost中提供演示 AbilityEmbedQtAbility,其页面通过EmbeddedComponent(want, EmbeddedType.EMBEDDED_UI_EXTENSION)指定要拉起的扩展能力名称与参数。 - Want 约定 :
EmbedQtAbility将bundleName设为当前应用包名,abilityName设为QEmbeddedUiExtensionAbility,并把启动参数中以io.qt.为前缀的项传入扩展,供 Qt 侧读取。
2. 工程与模块结构
2.1 应用标识(AppScope/app.json5)
应用级配置定义包名与版本信息,嵌入场景下 Want.bundleName 必须与之一致 (模板在代码中用 getBundleInfoForSelfSync 取当前包名,避免硬编码错误)。
json
//:ohostemplateforqtapplication_20260331/AppScope/app.json5
{
"app": {
"bundleName": "com.ohos.ohosqttemplate",
"configuration": "$profile:configuration",
"vendor": "example",
"versionCode": 1000000,
"versionName": "1.0.0",
"icon": "$media:app_icon",
"label": "$string:app_name"
}
}
2.2 多模块工程(build-profile.json5)
工程级 build-profile.json5 声明两个模块:entry (主模块,含 Qt 与嵌入式扩展)与 qEmbeddedUiExtensionHost (feature,演示嵌入宿主)。构建产物为同一应用包内的多个 HAP/HSP(以实际打包方式为准),因此 feature 中的 EmbeddedComponent 可以指向 entry 中声明的 embeddedUI 能力。
与 SDK 相关的字段示例(签名等本地路径略):
compatibleSdkVersion、targetSdkVersion:决定可用的 Ability / Extension API 集。modules数组:每项name+srcPath对应磁盘上的子工程目录。
2.3 entry 模块配置要点(entry/src/main/module.json5)
下列字段直接影响运行时行为,建议对照阅读。
| 配置项 | 本模板取值 | 含义说明 |
|---|---|---|
type |
entry |
应用主模块。 |
srcEntry |
./ets/qabilitystage/QAbilityStage.ets |
指定 AbilityStage 实现,用于多实例、多进程键值与 Qt 全局初始化钩子。 |
mainElement |
QAbility |
默认启动的 UIAbility 名称。 |
deviceTypes |
tablet、2in1 |
声明支持的设备类型;注释中说明 phone 与最小化还原存在已知问题(QTFOROH-1076)。 |
abilities → QAbility |
launchType: "specified"、isolationProcess: true |
多实例与独立进程相关配置,与 QAbilityStage.onAcceptWant / onNewProcessRequest 配合。 |
extensionAbilities |
两条 type: "embeddedUI" |
声明嵌入式 UI 扩展;extensionProcessMode 分别为 instance 与 bundle。 |
嵌入式扩展与主 Ability 的声明片段如下:
json
//:ohostemplateforqtapplication_20260331/entry/src/main/module.json5
"extensionAbilities": [
{
"name": "QEmbeddedUiExtensionAbility",
"srcEntry": "./ets/qability/QEmbeddedUiExtensionAbility.ets",
"icon": "$media:layered_image",
"type": "embeddedUI",
"description": "",
"exported": true,
"extensionProcessMode": "instance"
},
{
"name": "QBundledEmbeddedUiExtensionAbility",
"srcEntry": "./ets/qability/QBundledEmbeddedUiExtensionAbility.ets",
"icon": "$media:layered_image",
"type": "embeddedUI",
"description": "",
"exported": true,
"extensionProcessMode": "bundle"
}
],
"abilities": [
{
"name": "QAbility",
"srcEntry": "./ets/qability/QAbility.ets",
"launchType": "specified",
// ...
"exported": true,
"isolationProcess": true,
要点:type 必须为 embeddedUI ,否则系统不会按嵌入式 UI 扩展路由;exported: true 允许同应用内通过 Want 访问该能力名称。
2.4 feature 宿主模块(qEmbeddedUiExtensionHost/src/main/module.json5)
该模块 仅声明普通 UIAbility ,不声明 extensionAbilities;嵌入的扩展能力仍落在 entry 中,由运行时根据包内合并后的清单解析。
json
//:ohostemplateforqtapplication_20260331/qEmbeddedUiExtensionHost/src/main/module.json5
{
"module": {
"name": "qEmbeddedUiExtensionHost",
"type": "feature",
"description": "$string:module_desc",
"mainElement": "EmbedQtAbility",
"deviceTypes": [
"2in1",
"tablet"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EmbedQtAbility",
"srcEntry": "./ets/embedqtability/EmbedQtAbility.ets",
// ...
"exported": true,
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
]
}
],
}
}
mainElement: "EmbedQtAbility" 表示从桌面图标等方式启动该 feature 时,默认进入嵌入演示 Ability。
3. 代码链路:从进程启动到 Qt 绘制
3.1 AbilityStage 与 Qt 单次初始化(QAbilityStage.ets)
QAbilityStage 在普通模式与扩展模式下都会调用 qpa.setupQtApplication,区别是 uiExtensionMode 与 abilityClassName 。扩展能力首次 onCreate 时走 initQtAppContextInUiExtensionMode,确保 QPA 以嵌入扩展语义初始化。
ts
//:ohostemplateforqtapplication_20260331/entry/src/main/ets/qabilitystage/QAbilityStage.ets
private static initQtAppContextImpl(appContext: common.ApplicationContext, abilityClassName: string, uiExtensionMode: boolean): void {
if (!QAbilityStage.setupQtApplicationCalled) {
hilog.info(LOG_DOMAIN, LOG_TAG, 'QAbilityStage::initQtAppContextImpl: init with uiExtensionMode=' + uiExtensionMode);
QAbilityStage.setupQtApplicationCalled = true;
qpa.setupQtApplication({
appContext: appContext,
modules: QtUtils.getModulesMapForQt(),
appName: APP_LIBRARY_NAME,
appArgs: QAbilityStage.appArgs,
abilityClassName: abilityClassName,
uiExtensionMode: uiExtensionMode,
_unusedQChildProcess: new QChildProcess(),
});
} else {
hilog.info(LOG_DOMAIN, LOG_TAG, 'QAbilityStage::initQtAppContextImpl: already initialized');
}
}
public static initQtAppContextIfNeeded(appContext: common.ApplicationContext): void {
QAbilityStage.initQtAppContextImpl(appContext, QAbility.name, false);
}
public static initQtAppContextInUiExtensionMode(appContext: common.ApplicationContext, abilityClassName: string): void {
QAbilityStage.initQtAppContextImpl(appContext, abilityClassName, true);
}
APP_LIBRARY_NAME 来自 QtAppConstants.ets(当前为 libcalculator.so),需与部署到设备上的 Qt 应用库文件名一致。
ts
//:ohostemplateforqtapplication_20260331/entry/src/main/ets/common/QtAppConstants.ets
export const APP_LIBRARY_NAME = 'libcalculator.so';
export const LOG_DOMAIN = 0x0000;
export const LOG_TAG = 'ohosQtTemplate';
3.2 主 UIAbility:QAbility.ets
主入口将系统回调逐一交给 QPA,形成与原生鸿蒙应用一致的「创建 → 窗口阶段 → 前后台 → 销毁」节奏。
ts
//:ohostemplateforqtapplication_20260331/entry/src/main/ets/qability/QAbility.ets
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
hilog.info(LOG_DOMAIN, LOG_TAG, 'QAbility::onCreate(): want.parameters: ' + JSON.stringify(want.parameters));
QAbilityStage.initQtAppContextIfNeeded(this.context.getApplicationContext());
qpa.handleAbilityOnCreate(this, want, launchParam);
}
onDestroy(): void | Promise<void> {
hilog.info(LOG_DOMAIN, LOG_TAG, 'QAbility::onDestroy()');
return qpa.handleAbilityOnDestroy(this);
}
// ...
onWindowStageCreate(windowStage: Window.WindowStage) {
hilog.info(LOG_DOMAIN, LOG_TAG, 'QAbility::onWindowStageCreate(): this.launchWant.parameters: ' + JSON.stringify(this.launchWant.parameters));
qpa.handleAbilityOnWindowStageCreate(this, windowStage);
}
3.3 嵌入式扩展基类:QBaseEmbeddedUiExtensionAbility.ets
扩展侧在 onCreate 中调用 initQtAppContextInUiExtensionMode,随后各会话阶段同样进入 QPA。子类 QEmbeddedUiExtensionAbility / QBundledEmbeddedUiExtensionAbility 仅区分日志用的类名,行为一致。
ts
//:ohostemplateforqtapplication_20260331/entry/src/main/ets/qability/QBaseEmbeddedUiExtensionAbility.ets
onCreate(launchParam: AbilityConstant.LaunchParam): void {
hilog.info(LOG_DOMAIN, LOG_TAG, '%{public}s::onCreate()', this.getClassName());
QAbilityStage.initQtAppContextInUiExtensionMode(this.context.getApplicationContext(), this.getClassName());
qpa.handleQEmbeddedUiExtensionAbilityOnCreate(this, launchParam);
}
onDestroy(): void | Promise<void> {
hilog.info(LOG_DOMAIN, LOG_TAG, '%{public}s::onDestroy()', this.getClassName());
return qpa.handleQEmbeddedUiExtensionAbilityOnDestroy(this);
}
onSessionCreate(want: Want, session: UIExtensionContentSession): void {
hilog.info(LOG_DOMAIN, LOG_TAG, '%{public}s::onSessionCreate()', this.getClassName());
qpa.handleQEmbeddedUiExtensionAbilityOnSessionCreate(this, want, session);
}
onSessionDestroy(session: UIExtensionContentSession): void {
hilog.info(LOG_DOMAIN, LOG_TAG, '%{public}s::onSessionDestroy()', this.getClassName());
qpa.handleQEmbeddedUiExtensionAbilityOnSessionDestroy(this, session);
}
3.4 XComponent 与 qohos:主窗口与扩展会话页面
主窗口节点页面(示例为 MainWindowNativeNode.ets)与扩展内页面 UiExtensionNativeNode.ets 结构相同:在 Stack 中放置 XComponent,指定 libraryname: 'qohos',由 QPA 注册的 native 模块承接 Qt 场景图。
ts
//:ohostemplateforqtapplication_20260331/entry/src/main/ets/pages/MainWindowNativeNode.ets
build() {
Stack() {
if (this.createInfo !== undefined) {
XComponent({
type: XComponentType.NODE,
id: this.createInfo.xComponentId,
libraryname: 'qohos'
})
.onAttach(this.createInfo.onAttach)
.onAppear(this.createInfo.onAppear)
.onDisAppear(this.createInfo.onDisAppear)
.width('100%')
.height('100%')
}
}
ts
//:ohostemplateforqtapplication_20260331/entry/src/main/ets/pages/UiExtensionNativeNode.ets
if (this.createInfo !== undefined) {
XComponent({
type: XComponentType.NODE,
id: this.createInfo.xComponentId,
libraryname: 'qohos'
})
.onAppear(this.createInfo.onAppear)
.onDisAppear(this.createInfo.onDisAppear)
.onAttach(() => {
if (this.createInfo !== undefined) {
this.createInfo.onAttach?.(this.getUIContext());
} else {
hilog.error(LOG_DOMAIN, LOG_TAG, 'Cannot call onAttach, createInfo is undefined');
}
})
.width('100%')
.height('100%')
}
3.5 嵌入演示:EmbedQtAbility → Index → EmbeddedComponent
EmbedQtAbility 在 onWindowStageCreate 中过滤 io.qt.* 参数,构造指向 QEmbeddedUiExtensionAbility 的 Want,写入 LocalStorage 后加载 pages/Index。
ts
//:ohostemplateforqtapplication_20260331/qEmbeddedUiExtensionHost/src/main/ets/embedqtability/EmbedQtAbility.ets
onWindowStageCreate(windowStage: window.WindowStage): void {
const qtParameterPrefix: string = 'io.qt.';
let qtParameters: Record<string, Object> = {};
if (this.launchWant.parameters) {
Object.keys(this.launchWant.parameters)
.filter(key => key.startsWith(qtParameterPrefix))
.forEach(qtKey => qtParameters[qtKey] = this.launchWant.parameters![qtKey]);
}
let localStorageProperties: Record<string, Want> = {};
localStorageProperties[EmbedQtAbility.EMBEDDED_QT_START_WANT_PROP_NAME] = {
bundleName: bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT).name,
abilityName: 'QEmbeddedUiExtensionAbility',
parameters: qtParameters,
};
windowStage.loadContent('pages/Index', new LocalStorage(localStorageProperties))
}
Index.ets 取出上述 Want,交给 EmbeddedComponentImpl。
ts
//ohostemplateforqtapplication_20260331/qEmbeddedUiExtensionHost/src/main/ets/pages/Index.ets
@Entry
@Component
struct Index {
private want: Want = LocalStorage.getShared().get<Want>(EmbedQtAbility.EMBEDDED_QT_START_WANT_PROP_NAME) as Want;
build() {
Row() {
Column() {
EmbeddedComponentImpl({want: this.want})
.width('100%')
.height('100%')
}
.width('100%')
}
.height('100%')
}
}
EmbeddedComponentImpl.ets 中 EmbeddedComponent 的 want 不可省略 ,否则无法拉起嵌入式扩展;onTerminated / onError 用于观测嵌入失败或扩展退出。
ts
//ohostemplateforqtapplication_20260331/qEmbeddedUiExtensionHost/src/main/ets/components/EmbeddedComponentImpl.ets
build() {
Row() {
Column() {
Text("Hello from EmbeddedComponentImpl")
// This is the embedded component used to embed Qt application. Don't remove it.
EmbeddedComponent(this.want, EmbeddedType.EMBEDDED_UI_EXTENSION)
.width('100%')
.height('90%')
.onTerminated((info: TerminationInfo) => {
console.warn(`Terminarion: code = ${info.code}, want = ${JSON.stringify(info.want)}`);
})
.onError((error: BusinessError) => {
console.error(`Error: code = ${error.code}, message = '${JSON.stringify(error.message)}'`);
})
}
.width('100%')
}
.height('100%')
}
3.6 原生侧 entry 库(entry/src/main/cpp)
模板附带最小 libentry.so (hello.cpp + NAPI),与 libqohos.so、Qt 应用及 Qt 依赖库 分工不同:前者多为示例或胶水代码,Qt 运行主体由 QPA 与 Qt 共享库承担。CMake 仅声明 entry 与 libace_napi.z.so 链接,实际 Qt 库通过 entry/libs/<ABI>/ 部署。
bash
#ohostemplateforqtapplication_20260331/entry/src/main/cpp/CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
project(ohosQtTemplate)
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${NATIVERENDER_ROOT_PATH}
${NATIVERENDER_ROOT_PATH}/include)
add_library(entry SHARED hello.cpp)
target_link_libraries(entry PUBLIC libace_napi.z.so)
4. 生命周期与数据流小结
4.1 主 Ability 与扩展 Ability 对比
| 阶段 | QAbility(UIAbility) | QBaseEmbeddedUiExtensionAbility |
|---|---|---|
| 应用级 Qt 初始化 | initQtAppContextIfNeeded,uiExtensionMode: false |
initQtAppContextInUiExtensionMode,uiExtensionMode: true |
| 窗口 | onWindowStageCreate 等,由 QPA 绑定主 WindowStage |
无独立「全屏窗口阶段」语义;由 onSessionCreate 进入会话 UI |
| 会话 | 不适用 | onSessionCreate / onSessionDestroy 对应每次嵌入 |
| 原生绘制载体 | MainWindowNativeNode 中 XComponent |
UiExtensionNativeNode 中 XComponent |
4.2 整体数据流(示意)
entry
qEmbeddedUiExtensionHost
Want 指向同包扩展
EmbedQtAbility
LocalStorage 中的 Want
EmbeddedComponent
QEmbeddedUiExtensionAbility
libqohos.so / QPA
UiExtensionNativeNode XComponent
5. 集成与调试时注意点
- 库文件部署 :将 Qt 应用依赖的qt库的
.so、libqohos.so及依赖的 Qt 模块库复制到entry/libs/<ABI>/(如arm64-v8a、x86_64),与模拟器或真机 ABI 一致。 - 应用库名 :修改
QtAppConstants.ets中APP_LIBRARY_NAME,与目标.so文件名一致。 - 设备类型 :entry 与 host 模块当前均面向 平板 / 2in1 ;若需手机,需评估
module.json5注释中的最小化还原问题后再改deviceTypes。 - 嵌入目标 :演示页默认拉起
QEmbeddedUiExtensionAbility;若需改用QBundledEmbeddedUiExtensionAbility,应同步修改EmbedQtAbility.ets中的abilityName与测试场景。 - 日志 :统一 TAG 为
ohosQtTemplate(见QtAppConstants.ets),便于在 HiLog 中过滤主流程与扩展流程。
6. 与传统 PC 桌面 Qt 应用的差异
-
进程与入口不是 main() 独占
系统先按鸿蒙规则拉起 Ability。全屏场景走 QAbility(UIAbility);需要嵌在别的界面里时走 EmbeddedUIExtensionAbility 子类,由宿主页面的 EmbeddedComponent 触发会话。
-
Qt 由 QPA 插件接入系统,而不是直接对接 Win32/X11
ArkTS 通过 import qpa from 'libqohos.so' 把 onCreate / onWindowStageCreate / 前后台 / 销毁 以及扩展侧的 onSessionCreate / onSessionDestroy 等转给 Qt for OHOS 的 QPA(libqohos.so)。也就是说:鸿蒙生命周期 → NAPI → QPA → Qt 事件循环与窗口逻辑。
-
绘制表面是 ArkUI 的 XComponent,而不是系统原生 HWND 一层到底
主窗口和嵌入场景都在 ArkUI 里用 XComponent,type: NODE,libraryname: 'qohos' 留出一块原生区域;QPA 在这块 NODE 上挂接 OpenGL/渲染与输入。模板里对应 MainWindowNativeNode.ets 与 UiExtensionNativeNode.ets。
-
"可执行文件"形态是共享库 + 配置名
业务 Qt 程序一般是 entry/libs// 下的 .so(如 QtAppConstants.ets 里的 APP_LIBRARY_NAME),再配合 libqohos.so 和 Qt 依赖库 一起打包进 HAP。没有传统 PC 上那种用户双击的单一 .exe 作为主入口(入口是鸿蒙 Ability)。
-
全局初始化与多实例
QAbilityStage 里 setupQtApplication 只应执行一次,并区分普通模式与 uiExtensionMode: true 的嵌入模式;module.json5 里 launchType / isolationProcess 等与 onAcceptWant / onNewProcessRequest 一起服务于多实例、进程隔离等鸿蒙能力。
本模板工程中,Qt 并不是「从 main() 起独占进程、直接对接 Win32/X11/Wayland/Cocoa」的传统桌面形态,而是落在 HarmonyOS Ability 模型 之内:由 QAbility(UIAbility)或 EmbeddedUIExtensionAbility 子类 作为系统入口,经 libqohos.so 将 Ability / Session 生命周期交给 QPA,再把界面画在 ArkUI XComponent(libraryname: 'qohos') 所暴露的原生节点上。
除下表外,还可记住三点:入口在 Ability 而非仅 main() 、平台抽象层是 ohos QPA 而非 windows/xcb 等 、业务常以 .so + APP_LIBRARY_NAME 形式部署于 entry/libs/<ABI>/。
| 维度 | 传统 PC(Windows / Linux / macOS) | 本鸿蒙 Qt 模板(ohostemplateforqtapplication_20260331) |
|---|---|---|
| 程序入口 | main() 中创建 QApplication / QGuiApplication 并 exec() |
系统拉起 UIAbility / ExtensionAbility ;ArkTS 在 onCreate、onWindowStageCreate 等回调中调用 qpa.handleAbilityOnCreate 等,由 QPA 驱动 Qt |
| 平台插件(QPA) | windows、xcb / wayland、cocoa 等,直连各 OS 窗口与输入栈 |
libqohos.so ,衔接 Ability、WindowStage、扩展 Session 与 XComponent |
| 窗口与 UI 框架 | 以 Qt 窗口 (QWidget / QWindow)为主,占满或管理自有层级 |
ArkUI 页面 + XComponent 原生区域 ;全屏走 MainWindowNativeNode,嵌入走 UiExtensionNativeNode;宿主侧可用 EmbeddedComponent 拉起 EmbeddedUIExtensionAbility |
| 打包与部署 | 安装目录或安装包中的 可执行文件 (.exe / ELF)及依赖 DLL/so |
HAP 模块 ;Qt 应用多为 entry/libs/<ABI>/ 下的 .so ,与 libqohos.so、Qt 依赖库 一并随包安装;入口能力名在 module.json5 ,应用库名在 QtAppConstants.ets 的 APP_LIBRARY_NAME |
| 生命周期 | 进程启动到退出大致对应应用存活期,前后台多与窗口最小化等相关 | 与 Ability 前后台、WindowStage 创建销毁、嵌入场景的 onSessionCreate / onSessionDestroy 强绑定,需与 QPA 对齐 |
| 设备与系统能力 | 由桌面环境与用户权限模型决定 | 受 module.json5 中 deviceTypes 、权限声明 、多模块(entry + feature) 及 真机/模拟器 ABI 约束 |
桌面 Qt 可概括为「Qt 即应用外壳」;鸿蒙模板则是「系统 Ability + ArkUI 壳 + XComponent 锚点 + ohos QPA 」承载 Qt;嵌入能力再叠一层 同包 embeddedUI 扩展与 EmbeddedComponent 。从 PC 迁来时,需改写入口与打包形态,并在调试中习惯用 HiLog 与 Ability 状态 观察运行阶段,而非仅依赖桌面上的进程列表或控制台。
总结
鸿蒙版 Qt 项目模板 ohostemplateforqtapplication_20260331 通过 QAbility + libqohos.so 实现常规全屏 Qt 应用,通过 QBaseEmbeddedUiExtensionAbility + module.json5 中 embeddedUI 声明 提供可被 EmbeddedComponent 嵌入的能力,并在 feature 模块 中用 EmbedQtAbility → EmbeddedComponent 走完端到端演示链路。
理解本模板的关键在于:清单中的 extensionProcessMode 与 type: embeddedUI 、ArkTS 侧对 QPA 的生命周期转发 ,以及 XComponent NODE 与 libraryname: 'qohos' 作为 Qt 渲染锚点。在此基础上的业务开发,主要集中在 Qt 侧功能、APP_LIBRARY_NAME 与 Want 参数约定,以及权限与 deviceTypes 的调整。
最后,欢迎加入开源鸿蒙开发者社区交流:https://harmonypc.csdn.net/
附录:延伸阅读
以下链接供查阅嵌入式 UI 扩展与 HarmonyOS Ability 相关内容:
-
HarmonyOS 应用开发中 EmbeddedUIExtensionAbility:跨进程 UI 嵌入 - SegmentFault
-
https://wiki.qt.io/Qt5.12.12_Open_Source_Release_for_HarmonyOS_zh
官方文档请优先参考:HarmonyOS 开发者官网。