Qt for HarmonyOS/api inconsistencies on harmonyos zh: Difference between revisions
No edit summary |
No edit summary |
||
| Line 245: | Line 245: | ||
'''参考链接:''' | '''参考链接:''' | ||
* | * | ||
== 拖拽数据访问 == | |||
在桌面平台上,对于外部拖入的拖拽操作,应用通常可以在 dragEnterEvent 和 dragMoveEvent 阶段通过 mimeData() 访问拖拽数据内容。 | |||
在 HarmonyOS 平台上,对于外部拖入的拖拽操作,dragEnterEvent 和 dragMoveEvent 阶段通常只能获得 MIME 类型信息,不能获取真实的 QMimeData 数据内容。只有在 dropEvent 发生时,真实拖拽数据才会被转换为 QMimeData 提供给 Qt 应用。 | |||
'''建议:''' | |||
* 不要在 dragEnterEvent 或 dragMoveEvent 中依赖实际数据内容做判断 | |||
* 建议在拖拽进入和移动阶段仅根据 MIME 类型决定是否接受拖拽 | |||
* 需要读取实际数据内容时,应在 dropEvent 中处理 | |||
== 已知使用原则 == | == 已知使用原则 == | ||
Latest revision as of 06:52, 15 April 2026
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::WindowModal和Qt::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
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()都视为“用户点击关闭按钮”
- 建议在应用设计中区分窗口关闭与生命周期关闭两类场景
参考链接:
拖拽数据访问
在桌面平台上,对于外部拖入的拖拽操作,应用通常可以在 dragEnterEvent 和 dragMoveEvent 阶段通过 mimeData() 访问拖拽数据内容。
在 HarmonyOS 平台上,对于外部拖入的拖拽操作,dragEnterEvent 和 dragMoveEvent 阶段通常只能获得 MIME 类型信息,不能获取真实的 QMimeData 数据内容。只有在 dropEvent 发生时,真实拖拽数据才会被转换为 QMimeData 提供给 Qt 应用。
建议:
- 不要在 dragEnterEvent 或 dragMoveEvent 中依赖实际数据内容做判断
- 建议在拖拽进入和移动阶段仅根据 MIME 类型决定是否接受拖拽
- 需要读取实际数据内容时,应在 dropEvent 中处理
已知使用原则
在 HarmonyOS 平台上,以下能力不宜按桌面平台经验直接使用:
- 子窗口最小化
- 全应用级模态的桌面式语义
- 所有窗口统一支持标题栏按钮控制
- 所有窗口统一支持置顶
- 主窗口异形裁剪
- 将外部嵌入窗口当作普通 Qt 顶层窗口使用