HarmonyOS鸿蒙PC的QT应用开发:QT项目运行原理与 EmbeddedUIExtensionAbility介绍

HarmonyOS鸿蒙PC的QT应用开发:QT项目运行原理与 EmbeddedUIExtensionAbility介绍
好消息,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.json5ArkTS 与原生库调用关系,说明模板工程的运行原理,并单独梳理 EmbeddedUIExtensionAbility 在本项目中的职责与数据流。文中代码与配置均来自当前仓库快照;系统 API 行为以你所使用的 HarmonyOS SDK 版本及官方文档为准。


1. 核心概念

1.1 Qt 在鸿蒙模板中的位置

  • 入口形态:模板将 主界面 实现为 UIAbility 子类 QAbility,生命周期各阶段委托给 libqohos.so 暴露的 NAPI(代码中以 import qpa from 'libqohos.so' 引用),由 Qt for OpenHarmony / HarmonyOS 的 QPA 与系统窗口、输入等对接。
  • 绘制落点:ArkUI 页面通过 XComponenttype: XComponentType.NODElibraryname: 'qohos' 创建原生节点;QPA 在该节点上挂载 Qt 的渲染与事件循环逻辑。主窗口与嵌入扩展会话各对应一套页面与节点,但共用同一套 qohos 原生模块名。
  • 业务库:实际运行的 Qt 可执行形态为共享库(如 libcalculator.so),名称在 QtAppConstants.etsAPP_LIBRARY_NAME 中配置,并需与 entry/libs/<ABI>/ 下放置的 .so 一致。

1.2 EmbeddedUIExtensionAbility 在本项目中的角色

  • 系统定义EmbeddedUIExtensionAbility 是嵌入式 UI 类扩展能力,与 UIExtension 会话(UIExtensionContentSession 绑定;每次嵌入对应一次会话创建与销毁。
  • 模板封装QBaseEmbeddedUiExtensionAbility 继承系统基类,在 onCreateonSessionCreateonSessionDestroyonDestroy 中统一转发到 qpa.handleQEmbeddedUiExtensionAbility*;并在首次创建时用 uiExtensionMode: true 初始化 Qt 应用上下文,使 QPA 按「扩展嵌入」路径而非普通全屏 Ability 路径工作。
  • 双扩展名module.json5 声明了两个嵌入式扩展:QEmbeddedUiExtensionAbilityextensionProcessMode: "instance")与 QBundledEmbeddedUiExtensionAbilityextensionProcessMode: "bundle"),便于在同一模板内对比或选用不同进程/打包语义(具体调度以系统实现为准)。

1.3 宿主侧 EmbeddedComponent

  • 使用位置:模板在 feature 模块qEmbeddedUiExtensionHost 中提供演示 Ability EmbedQtAbility,其页面通过 EmbeddedComponent(want, EmbeddedType.EMBEDDED_UI_EXTENSION) 指定要拉起的扩展能力名称与参数。
  • Want 约定EmbedQtAbilitybundleName 设为当前应用包名,abilityName 设为 QEmbeddedUiExtensionAbility,并把启动参数中以 io.qt. 为前缀的项传入扩展,供 Qt 侧读取。

2. 工程与模块结构

2.1 应用标识(AppScope/app.json5)

应用级配置定义包名与版本信息,嵌入场景下 Want.bundleName 必须与之一致(模板在代码中用 getBundleInfoForSelfSync 取当前包名,避免硬编码错误)。

//: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 相关的字段示例(签名等本地路径略):

  • compatibleSdkVersiontargetSdkVersion:决定可用的 Ability / Extension API 集。
  • modules 数组:每项 name + srcPath 对应磁盘上的子工程目录。

2.3 entry 模块配置要点(entry/src/main/module.json5)

下列字段直接影响运行时行为,建议对照阅读。

配置项本模板取值含义说明
typeentry应用主模块。
srcEntry./ets/qabilitystage/QAbilityStage.ets指定 AbilityStage 实现,用于多实例、多进程键值与 Qt 全局初始化钩子。
mainElementQAbility默认启动的 UIAbility 名称。
deviceTypestablet2in1声明支持的设备类型;注释中说明 phone 与最小化还原存在已知问题(QTFOROH-1076)。
abilitiesQAbilitylaunchType: "specified"isolationProcess: true多实例与独立进程相关配置,与 QAbilityStage.onAcceptWant / onNewProcessRequest 配合。
extensionAbilities两条 type: "embeddedUI"声明嵌入式 UI 扩展;extensionProcessMode 分别为 instancebundle

嵌入式扩展与主 Ability 的声明片段如下:

//: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 中,由运行时根据包内合并后的清单解析。

//: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,区别是 uiExtensionModeabilityClassName。扩展能力首次 onCreate 时走 initQtAppContextInUiExtensionMode,确保 QPA 以嵌入扩展语义初始化。

//:ohostemplateforqtapplication_20260331/entry/src/main/ets/qabilitystage/QAbilityStage.etsprivatestaticinitQtAppContextImpl(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:newQChildProcess(),});}else{ hilog.info(LOG_DOMAIN,LOG_TAG,'QAbilityStage::initQtAppContextImpl: already initialized');}}publicstaticinitQtAppContextIfNeeded(appContext: common.ApplicationContext):void{ QAbilityStage.initQtAppContextImpl(appContext, QAbility.name,false);}publicstaticinitQtAppContextInUiExtensionMode(appContext: common.ApplicationContext, abilityClassName:string):void{ QAbilityStage.initQtAppContextImpl(appContext, abilityClassName,true);}

APP_LIBRARY_NAME 来自 QtAppConstants.ets(当前为 libcalculator.so),需与部署到设备上的 Qt 应用库文件名一致。

//:ohostemplateforqtapplication_20260331/entry/src/main/ets/common/QtAppConstants.etsexportconstAPP_LIBRARY_NAME='libcalculator.so';exportconstLOG_DOMAIN=0x0000;exportconstLOG_TAG='ohosQtTemplate';

3.2 主 UIAbility:QAbility.ets

主入口将系统回调逐一交给 QPA,形成与原生鸿蒙应用一致的「创建 → 窗口阶段 → 前后台 → 销毁」节奏。

//:ohostemplateforqtapplication_20260331/entry/src/main/ets/qability/QAbility.etsonCreate(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 仅区分日志用的类名,行为一致。

//:ohostemplateforqtapplication_20260331/entry/src/main/ets/qability/QBaseEmbeddedUiExtensionAbility.etsonCreate(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 场景图。

//:ohostemplateforqtapplication_20260331/entry/src/main/ets/pages/MainWindowNativeNode.etsbuild(){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%')}}
//:ohostemplateforqtapplication_20260331/entry/src/main/ets/pages/UiExtensionNativeNode.etsif(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

EmbedQtAbilityonWindowStageCreate 中过滤 io.qt.* 参数,构造指向 QEmbeddedUiExtensionAbilityWant,写入 LocalStorage 后加载 pages/Index

//:ohostemplateforqtapplication_20260331/qEmbeddedUiExtensionHost/src/main/ets/embedqtability/EmbedQtAbility.etsonWindowStageCreate(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',newLocalStorage(localStorageProperties))}

Index.ets 取出上述 Want,交给 EmbeddedComponentImpl

//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.etsEmbeddedComponentwant 不可省略,否则无法拉起嵌入式扩展;onTerminated / onError 用于观测嵌入失败或扩展退出。

//ohostemplateforqtapplication_20260331/qEmbeddedUiExtensionHost/src/main/ets/components/EmbeddedComponentImpl.etsbuild(){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.sohello.cpp + NAPI),与 libqohos.so、Qt 应用及 Qt 依赖库 分工不同:前者多为示例或胶水代码,Qt 运行主体由 QPA 与 Qt 共享库承担。CMake 仅声明 entrylibace_napi.z.so 链接,实际 Qt 库通过 entry/libs/<ABI>/ 部署。

#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 初始化initQtAppContextIfNeededuiExtensionMode: falseinitQtAppContextInUiExtensionModeuiExtensionMode: true
窗口onWindowStageCreate 等,由 QPA 绑定主 WindowStage无独立「全屏窗口阶段」语义;由 onSessionCreate 进入会话 UI
会话不适用onSessionCreate / onSessionDestroy 对应每次嵌入
原生绘制载体MainWindowNativeNode 中 XComponentUiExtensionNativeNode 中 XComponent

4.2 整体数据流(示意)

entry

qEmbeddedUiExtensionHost

Want 指向同包扩展

EmbedQtAbility

LocalStorage 中的 Want

EmbeddedComponent

QEmbeddedUiExtensionAbility

libqohos.so / QPA

UiExtensionNativeNode XComponent


5. 集成与调试时注意点

  1. 库文件部署:将 Qt 应用依赖的qt库的 .solibqohos.so 及依赖的 Qt 模块库复制到 entry/libs/<ABI>/(如 arm64-v8ax86_64),与模拟器或真机 ABI 一致。
  2. 应用库名:修改 QtAppConstants.etsAPP_LIBRARY_NAME,与目标 .so 文件名一致。
  3. 设备类型:entry 与 host 模块当前均面向 平板 / 2in1;若需手机,需评估 module.json5 注释中的最小化还原问题后再改 deviceTypes
  4. 嵌入目标:演示页默认拉起 QEmbeddedUiExtensionAbility;若需改用 QBundledEmbeddedUiExtensionAbility,应同步修改 EmbedQtAbility.ets 中的 abilityName 与测试场景。
  5. 日志:统一 TAG 为 ohosQtTemplate(见 QtAppConstants.ets),便于在 HiLog 中过滤主流程与扩展流程。

6. 与传统 PC 桌面 Qt 应用的差异

  1. 进程与入口不是 main() 独占
    系统先按鸿蒙规则拉起 Ability。全屏场景走 QAbility(UIAbility);需要嵌在别的界面里时走 EmbeddedUIExtensionAbility 子类,由宿主页面的 EmbeddedComponent 触发会话。
  2. Qt 由 QPA 插件接入系统,而不是直接对接 Win32/X11
    ArkTS 通过 import qpa from ‘libqohos.so’ 把 onCreate / onWindowStageCreate / 前后台 / 销毁 以及扩展侧的 onSessionCreate / onSessionDestroy 等转给 Qt for OHOS 的 QPA(libqohos.so)。也就是说:鸿蒙生命周期 → NAPI → QPA → Qt 事件循环与窗口逻辑。
  3. 绘制表面是 ArkUI 的 XComponent,而不是系统原生 HWND 一层到底
    主窗口和嵌入场景都在 ArkUI 里用 XComponent,type: NODE,libraryname: ‘qohos’ 留出一块原生区域;QPA 在这块 NODE 上挂接 OpenGL/渲染与输入。模板里对应 MainWindowNativeNode.ets 与 UiExtensionNativeNode.ets。
  4. “可执行文件”形态是共享库 + 配置名
    业务 Qt 程序一般是 entry/libs// 下的 .so(如 QtAppConstants.ets 里的 APP_LIBRARY_NAME),再配合 libqohos.so 和 Qt 依赖库 一起打包进 HAP。没有传统 PC 上那种用户双击的单一 .exe 作为主入口(入口是鸿蒙 Ability)。
  5. 全局初始化与多实例
    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 XComponentlibraryname: 'qohos' 所暴露的原生节点上。

除下表外,还可记住三点:入口在 Ability 而非仅 main()平台抽象层是 ohos QPA 而非 windows/xcb 等业务常以 .so + APP_LIBRARY_NAME 形式部署于 entry/libs/<ABI>/

维度传统 PC(Windows / Linux / macOS)本鸿蒙 Qt 模板(ohostemplateforqtapplication_20260331
程序入口main() 中创建 QApplication / QGuiApplicationexec()系统拉起 UIAbility / ExtensionAbility;ArkTS 在 onCreateonWindowStageCreate 等回调中调用 qpa.handleAbilityOnCreate 等,由 QPA 驱动 Qt
平台插件(QPA)windowsxcb / waylandcocoa 等,直连各 OS 窗口与输入栈libqohos.so,衔接 Ability、WindowStage、扩展 SessionXComponent
窗口与 UI 框架Qt 窗口QWidget / QWindow)为主,占满或管理自有层级ArkUI 页面 + XComponent 原生区域;全屏走 MainWindowNativeNode,嵌入走 UiExtensionNativeNode;宿主侧可用 EmbeddedComponent 拉起 EmbeddedUIExtensionAbility
打包与部署安装目录或安装包中的 可执行文件.exe / ELF)及依赖 DLL/soHAP 模块;Qt 应用多为 entry/libs/<ABI>/ 下的 .so,与 libqohos.so、Qt 依赖库 一并随包安装;入口能力名在 module.json5,应用库名在 QtAppConstants.etsAPP_LIBRARY_NAME
生命周期进程启动到退出大致对应应用存活期,前后台多与窗口最小化等相关Ability 前后台、WindowStage 创建销毁、嵌入场景的 onSessionCreate / onSessionDestroy 强绑定,需与 QPA 对齐
设备与系统能力由桌面环境与用户权限模型决定module.json5deviceTypes权限声明多模块(entry + feature)真机/模拟器 ABI 约束

桌面 Qt 可概括为「Qt 即应用外壳」;鸿蒙模板则是「系统 Ability + ArkUI 壳 + XComponent 锚点 + ohos QPA」承载 Qt;嵌入能力再叠一层 同包 embeddedUI 扩展与 EmbeddedComponent。从 PC 迁来时,需改写入口与打包形态,并在调试中习惯用 HiLogAbility 状态 观察运行阶段,而非仅依赖桌面上的进程列表或控制台。


总结

鸿蒙版 Qt 项目模板 ohostemplateforqtapplication_20260331 通过 QAbility + libqohos.so 实现常规全屏 Qt 应用,通过 QBaseEmbeddedUiExtensionAbility + module.json5embeddedUI 声明 提供可被 EmbeddedComponent 嵌入的能力,并在 feature 模块 中用 EmbedQtAbilityEmbeddedComponent 走完端到端演示链路。

理解本模板的关键在于:清单中的 extensionProcessModetype: embeddedUIArkTS 侧对 QPA 的生命周期转发,以及 XComponent NODE 与 libraryname: 'qohos' 作为 Qt 渲染锚点。在此基础上的业务开发,主要集中在 Qt 侧功能、APP_LIBRARY_NAME 与 Want 参数约定,以及权限与 deviceTypes 的调整。


最后,欢迎加入开源鸿蒙开发者社区交流:https://harmonypc.ZEEKLOG.net/

附录:延伸阅读

以下链接供查阅嵌入式 UI 扩展与 HarmonyOS Ability 相关内容:

  1. HarmonyOS 嵌入式 UI 扩展组件实战 - 博客园
  2. HarmonyOS 应用开发中 EmbeddedUIExtensionAbility:跨进程 UI 嵌入 - SegmentFault
  3. 知乎专栏
  4. https://wiki.qt.io/Qt_for_OpenHarmony/zh?login=from_ZEEKLOG
  5. https://wiki.qt.io/Qt5.12.12_Open_Source_Release_for_HarmonyOS_zh

官方文档请优先参考:HarmonyOS 开发者官网

Read more

SpringAI 大模型应用开发篇-SpringAI 项目的新手入门知识

SpringAI 大模型应用开发篇-SpringAI 项目的新手入门知识

🔥博客主页: 【小扳_-ZEEKLOG博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录         1.0 SpringAI 概述         1.1 大模型的使用         2.0 SpringAI 新手入门         2.1 配置 pom.xml 文件         2.2 配置 application.yaml 文件         2.3 配置 ChatClient         2.4 同步调用         2.5 流式调用         2.6 System 设定         2.7 日志功能         2.8 会话记忆功能

最新更新版本,OpenClaw v2026.4.2 深度解读剖析:Task Flow 重磅回归与安全架构的全面硬化

最新更新版本,OpenClaw v2026.4.2 深度解读剖析:Task Flow 重磅回归与安全架构的全面硬化

文档版本:v1.0 分析基准日期:2026年4月3日 字数统计:约20,000字 分析维度:架构演进、功能解析、安全机制、生态影响、升级指南、未来展望 第一章:版本总览——一次功能与安全并重的里程碑式更新 1.1 发布背景与战略定位 2026年4月3日,OpenClaw 正式发布 v2026.4.2 版本。这并非一次常规的迭代更新,而是在经历了2026年3月一系列架构大手术(v2026.3.7 的 ContextEngine 插件化、v2026.3.31 的核心架构重塑)之后,项目进入**"能力回归与安全硬化"**阶段的关键里程碑。 从版本号演进来看,v2026.4.2

Python + Selenium + AI 智能爬虫:自动识别反爬与数据提取

Python + Selenium + AI 智能爬虫:自动识别反爬与数据提取

结合 Selenium 浏览器自动化与 AI 大模型能力,构建能够自动识别反爬机制、智能解析页面的新一代爬虫系统。 1. 系统架构 验证码 登录墙 正常页面 种子 URL 队列 调度器 Selenium WebDriver 反检测模块 页面渲染 AI 反爬识别 AI 验证码破解 自动登录 AI 数据提取 数据清洗管道 存储 MongoDB / CSV 数据看板 2. 反爬机制分布 35%25%20%10%7%3%常见反爬机制占比(Top 500 网站统计)JS 动态渲染请求频率限制验证码(图形/滑块)User-Agent 检测IP