Jump to content

Qt for HarmonyOS/api inconsistencies on harmonyos zh

From Qt Wiki

Qt for HarmonyOS:API 兼容性注意事项

本文档说明 Qt 在 HarmonyOS 平台上与其他常见平台(如 Windows、Linux、macOS、Android)相比,在 public API 使用层面的主要差异与限制。

本文档仅描述会影响应用开发和跨平台移植的接口行为差异,不展开平台内部实现细节。

应用启动与参数传递

main(int argc, char *argv[])

在其他平台上, argv[0]通常表示可执行文件路径,业务参数一般从argv[1]开始。

在 HarmonyOS 平台上,Qt 应用的启动参数来源和拼接方式与传统桌面平台不同:

  • argv[0]表示应用库路径,而不是传统意义上的可执行文件路径
  • 通过 Want 传参时,want.uri默认可能占用argv[1]
  • 因此,业务参数在argv中的位置可能与其他平台不同

建议:

  • 不要假定业务参数固定从argv[1]开始
  • 建议在应用中按实际argc/argv内容解析参数

参考链接: https://wiki.qt.io/Qt_for_HarmonyOS/user_development_guide/how_to_pass_args_to_main_guiad_zh

启动另一个应用实例或进程

在桌面平台上,应用通常通过可执行文件路径启动另一个进程。

在 HarmonyOS 平台上,启动新实例或新进程的方式依赖系统 Ability/Want/进程管理机制,而不是传统桌面平台的可执行文件启动模型。Qt for HarmonyOS 提供的相关能力更接近“启动 Ability / 启动应用进程实例”,而不是“运行任意外部程序”。

相关公共接口包括:

  • QtOhosExtras::startAbility()
  • QtOhosExtras::startNewAbilityInstance()
  • QtOhosExtras::startAppProcess()

建议:

  • 不要按桌面平台“给一个可执行文件路径即可启动”的方式理解 HarmonyOS 进程启动模型
  • 跨实例或跨进程启动应优先使用 HarmonyOS 对应的 Ability/Want 接口

参考链接: https://wiki.qt.io/Qt_for_HarmonyOS/user_development_guide/application_lifecycle_guide_zh

无 UI 子进程

在桌面平台上,子进程通常可按普通进程理解,是否带界面主要由被启动程序自身决定。

在 HarmonyOS 平台上,Qt 提供了专门的“无 UI 子进程”能力:QtOhosExtras::QOhosAppContext::startNoUiChildProcess()。该接口通过 HarmonyOS Child Process Manager 启动子进程,传入的参数会转发到子进程的 main()

子进程启动后会进入专门的 NoUiChildProcess 运行模式。该模式与普通 UI 应用进程不同,其 Qt 平台能力会受到限制。

当前实现中,无 UI 子进程不会初始化或提供普通 UI 进程具备的若干能力。

应用可通过 QtOhosExtras::QOhosAppContext::isNoUiChildMode()判断当前进程是否处于无 UI 子进程模式。

建议:

  • 无 UI 子进程应仅用于计算、后台任务、辅助处理等无界面场景
  • 不要在无 UI 子进程中假定可以创建或操作普通窗口/UI 能力

参考链接: https://wiki.qt.io/Qt_for_HarmonyOS/user_development_guide/how_to_start_uiless_child_process_zh

QProcess

在桌面平台上,QProcess 通常可作为通用子进程启动接口,用于启动外部程序、辅助进程或独立 GUI 进程。

在 HarmonyOS 平台上,进程模型与桌面平台不同。Qt for HarmonyOS 中受支持、明确的平台子进程路径是 QtOhosExtras::QOhosAppContext::startNoUiChildProcess(),而不是将 QProcess 视为与桌面平台完全等价的通用进程启动方案。

因此,不应假定 QProcess 在 HarmonyOS 上具备与 Windows、Linux、macOS 相同的行为,包括但不限于:

  • 启动任意外部可执行程序
  • 启动独立 GUI 子进程
  • 具备与桌面平台一致的 start()、startDetached()、execute()语义

建议:

  • 不要将 QProcess 作为 HarmonyOS 上启动 Qt 子进程的推荐方案
  • 对无界面子进程,优先使用 QtOhosExtras::QOhosAppContext::startNoUiChildProcess()
  • 对有界面进程或者独立应用,建议使用QtOhosExtras::startAbility()启动。

窗口类型与窗口关系

QDialog、Qt::Popup、Qt::ToolTip、Qt::Tool

在桌面平台上,这些窗口类型通常可按独立顶层窗口方式理解和使用。

在 HarmonyOS 平台上,这些窗口类型更接近依附主窗口的子窗口语义,其行为在以下方面与其他平台存在差异:

  • 父子关系更重要
  • 激活行为更依赖主窗口
  • 关闭行为通常与主窗口生命周期更相关

建议:

  • 建议显式设置父窗口或transientParent
  • 不要按完全独立顶层窗口的方式设计这些窗口


参考链接: https://wiki.qt.io/Qt_for_HarmonyOS/user_development_guide/mainwindow_and_subwindow_guide_zh

setParent()/ reparent

在其他平台上,部分窗口类型允许较自由地调整父子关系。

在 HarmonyOS 平台上,与嵌入窗口或外部窗口相关的父子关系存在额外限制,不能按普通顶层窗口的方式自由重设。

建议:

  • 不要将外部嵌入窗口按普通父窗口使用
  • 在窗口重设父子关系前,应确认该窗口是否属于普通 Qt 窗口路径

参考链接: https://wiki.qt.io/Qt_for_HarmonyOS/user_development_guide/embedded_subwindow_guide_zh

模态、最小化/全屏显示/隐藏与窗口状态

Qt::WindowModality

在桌面平台上,Qt::WindowModalQt::ApplicationModal通常都具有明确且完整的模态语义。

在 HarmonyOS 平台上:

  • 模态能力主要针对子窗口场景
  • Qt::ApplicationModal不应简单理解为与桌面平台完全一致的全应用级模态行为,Qt::ApplicationModal 在 HarmonyOS 上不是桌面平台意义上的全应用级模态。当前实现中,它仅对子窗口场景有意义;仅在支持自由多窗的设备或者2-in-1设备上可用。

建议:

  • 优先按子窗口模态设计应用行为
  • 不要依赖桌面平台意义上的全局应用模态

参考链接 : https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-window-e#modalitytype14

showFullScreen()/ Qt::WindowFullScreen

在桌面平台上,showFullScreen()通常表示将窗口切换为全屏显示状态。

在 HarmonyOS 平台上,showFullScreen() 是受支持的。运行时调用该接口时,Qt 会将主窗口切换到 HarmonyOS 对应的全屏显示路径,并支持后续恢复到其他窗口状态。

对于由 Qt 新创建的主窗口,如果窗口在创建前已经设置为 Qt::WindowFullScreen,Qt 会在启动阶段将全屏模式作为窗口启动参数传递给 HarmonyOS。

需要注意的是,首个主窗口的创建路径与后续新建窗口不同。首个主窗口可能走平台自动创建的已有主窗口路径,因此首个主窗口不支持“启动即全屏”行为,后续新建主窗口才支持此特性。

建议:

  • 不要将首个主窗口和后续新建主窗口视为完全相同的全屏启动场景
  • 如需稳定的全屏行为,建议在窗口创建并显示后调用 showFullScreen() 或设置 Qt::WindowFullScreen

参考链接: https://wiki.qt.io/Qt_for_HarmonyOS/user_development_guide/qt_for_harmonyos_fullscreen_main_window_zh

showMinimized() / Qt::WindowMinimized

在其他平台上,最小化通常是标准顶层窗口能力,某些平台对子窗口也可能提供类似能力。

在 HarmonyOS 平台上:

  • 主窗口支持最小化语义
  • 子窗口不支持与桌面平台一致的最小化行为

建议:

  • 仅将最小化能力用于主窗口
  • 不要为子窗口设计依赖最小化状态的交互逻辑

hide()

在桌面平台上,hide() 通常可理解为通用的窗口隐藏能力。

HarmonyOS 平台上,hide() 不是通用窗口能力。对于主窗口,hide() 会优先尝试系统级隐藏,系统只支持带托盘的主窗口隐藏;如果系统不支持,则回退为最小化。对于子窗口和浮动窗口,hide() 可以隐藏当前窗口,不具有主窗口级别的系统隐藏语义。

建议:

  • 不要在 QWidget::closeEvent() 中将 hide() 作为通用“替代关闭”方案
  • 对主窗口保活场景,建议优先使用 showMinimized()
  • 对子窗口和浮动窗口,不要按主窗口隐藏语义理解 hide()

窗口 flag 与标题栏相关能力

Qt::WindowMinimizeButtonHint、Qt::WindowMaximizeButtonHint、Qt::WindowCloseButtonHint

在其他平台上,这些 flag 常用于控制标题栏按钮显示。

在 HarmonyOS 平台上,这些能力并非对所有窗口类型都有效:

  • 主要针对主窗口
  • 通常仅在 PC 模式下有意义
  • 子窗口不保证具有与其他平台一致的表现

建议:

  • 不要将这些 flag 视为跨设备、跨窗口类型的稳定能力
  • 应在设计上允许这些 hint 不生效

Qt::FramelessWindowHint

在桌面平台上,该 flag 通常用于表示无边框窗口。

在 HarmonyOS 平台上,Qt::FramelessWindowHint 主要对主窗口和子窗口生效,并会隐藏系统窗口装饰。 对于主窗口,启用该 flag 后,标题栏标准三键(最小化、最大化、关闭)也会一并不可用。

建议:

  • 使用该 flag 后,不应再假定标题栏按钮能力仍保持与其他平台一致

Qt::WindowStaysOnTopHint

在其他平台上,该 flag 常用于实现窗口置顶。

在 HarmonyOS 平台上,该能力具有更强的平台条件限制:

  • 主要针对主窗口
  • 通常仅在 PC 模式下有效

建议:

  • 仅在主窗口场景考虑使用该能力
  • 不要假定对子窗口同样有效

窗口形状与裁剪

setMask()

在桌面平台上,setMask() 常用于实现异形窗口或区域裁剪。

在 HarmonyOS 平台上,setMask() 仅对子窗口生效,不支持用于主窗口。

建议:

  • 不要将 setMask() 用于主窗口异形裁剪
  • 如需实现主窗口特殊外观,建议使用应用内容层面的裁剪或自定义绘制方案

窗口记忆(Window Geometry Persistence)

与其他平台通常通过 QSettings 由应用自行保存和恢复窗口位置、大小不同,HarmonyOS 平台上的窗口记忆能力依赖系统窗口管理能力,并通过 QtOhosExtras::setMainWindowGeometryPersistenceHint()提供公共接口进行控制。

该能力当前仅面向首个主窗口,并且必须在首个主窗口显示前设置;在首个主窗口显示后再调用该接口,不会更新窗口记忆策略。

此外,该能力目前仅支持 2-in-1 设备。

窗口关闭语义

closeEvent(QCloseEvent *)

在桌面平台上,closeEvent()通常主要表示窗口关闭动作。

在 HarmonyOS 平台上,关闭事件除窗口关闭外,还可能来自 Ability 生命周期关闭,因此其来源语义与其他平台不同。

建议:

  • 不要将所有closeEvent()都视为“用户点击关闭按钮”
  • 建议在应用设计中区分窗口关闭与生命周期关闭两类场景

参考链接: https://wiki.qt.io/Qt_for_HarmonyOS/user_development_guide/application_lifecycle_guide_zh#%E5%BA%94%E7%94%A8%E9%80%80%E5%87%BA

参考链接:

拖拽数据访问

在桌面平台上,对于外部拖入的拖拽操作,应用通常可以在 dragEnterEvent 和 dragMoveEvent 阶段通过 mimeData() 访问拖拽数据内容。

在 HarmonyOS 平台上,对于外部拖入的拖拽操作,dragEnterEvent 和 dragMoveEvent 阶段通常只能获得 MIME 类型信息,不能获取真实的 QMimeData 数据内容。只有在 dropEvent 发生时,真实拖拽数据才会被转换为 QMimeData 提供给 Qt 应用。

建议:

  • 不要在 dragEnterEvent 或 dragMoveEvent 中依赖实际数据内容做判断
  • 建议在拖拽进入和移动阶段仅根据 MIME 类型决定是否接受拖拽
  • 需要读取实际数据内容时,应在 dropEvent 中处理

已知使用原则

在 HarmonyOS 平台上,以下能力不宜按桌面平台经验直接使用:

  • 子窗口最小化
  • 全应用级模态的桌面式语义
  • 所有窗口统一支持标题栏按钮控制
  • 所有窗口统一支持置顶
  • 主窗口异形裁剪
  • 将外部嵌入窗口当作普通 Qt 顶层窗口使用