首页/文章/ 详情

技术文档丨Qt在HarmonyOS上的主窗口与子窗口开发指南

8月前浏览331

1

主窗口与子窗口概念

1.1 HarmonyOS的主窗口与子窗口

  • 主窗口:代表一个"任务"的窗口,有Dock栏图标和任务图标(Alt+Tab切换任务时),一般有独立的生命周期,可最大化、最小化、窗口化

  • 子窗口:任务产生的某个子功能的交互界面,是独立窗口可在主窗口以外显示,但无Dock栏图标和任务图标,必须从属于一个主窗口,主窗口关闭时会联动关闭,主窗口最小化时联动隐藏,主窗口恢复显示时联动恢复显示。一般在鸿蒙上对应各种弹窗和对话框。

1.2 Qt Widget或窗口创建

Qt创建Widget、Window时并无类似HarmonyOS的主、子关系的概念(部分widget如QDialog有Transient Parent概念,该概念与HarmonyOS主、子窗口接近)


示例:



















// 独立窗口QWidget w;w.show();
// 有父子关系的窗口(假设w关联了一个原生窗口)QWidget wp;wp.show();QWidget w(&wp);
// 对话框QDialog dlg;dlg.exec();
// 有父窗口的对话框(Transient Parent)QWidget w;w.show();QDialog dlg(&w);dlg.exec();
   


2

HarmonyOS适配规则

2.1 核心规则

1

标记函数:使用QOhosFunctions::tagWindowOrWidgetAsSubWindowOf(QObject *windowOrWidgetToTag, QWindow *mainWindow)函数,用于告诉Qt在为指定的顶层窗口创建HarmonyOS原生窗口时创建OHOS的子窗口,并指定其父窗口。该接口需要在mainWindow已创建,subWindow创建前调用。

2

首个窗口规则:进程的首个QWindow(或者无父亲的QWidget)创建时,会自动绑定到系统为应用创建的首个主窗口。

3

后续窗口规则:非首个QWindow(或者无父节点的QWidget)创建时,如果没有指定AsSubWindowOf标签,它将会创建一个OHOS的主窗口。

4

Transient Parent处理:对于Qt原生就有Transient Parent的QWidget对象(如QDialog的构造函数中可以传递Transient Parent对象),如果开发者传递了Transient Parent,则该对象的主窗口为Transient Parent对应的主窗口;如果没有传递,与普通的QWidget确定主窗口的方法相同。

5

自动Fallback机制:当标记的父窗口无效时,系统会自动为特定类型的窗口(如Qt::Popup、Qt::ToolTip、Qt::Dialog、Qt::Tool)寻找合适的父窗口:

  • 优先使用当前有焦点的窗口

  • 其次使用第一个可用的顶级窗口

  • 确保窗口总能找到合适的父窗口

2.2 开发建议

开发者需要理解HarmonyOS的主、子窗口概念,并在使用Qt时注意新创建的顶层Widget(无parent)是否需要创建HarmonyOS的子窗口,如果需要,则需要调用QOhosFunctions::tagWindowOrWidgetAsSubWindowOf() 函数,并指定其父窗口。


以下几种情况可以简化处理:

  • 单实例应用:如果应用为单实例(即单主窗口),需要在创建子窗口时调用AsSubWindowOf标签。

  • 多实例应用:如果应用有多实例(即单进程多主窗口),但所有子窗口的弹出均是用户通过操作界面触发,则需要在创建子窗口时调用AsSubWindowOf标签,创建新的主窗口不需要特殊操作。

  • Transient Parent窗口:如果创建QDialog等支持Transient Parent的QWidget,且传递了Transient Parent参数,则无需调用AsSubWindowOf标签,使用默认行为即可。


3

接口说明

3.1 主要函数


static void QOhosFunctions::tagWindowOrWidgetAsSubWindowOf(QObject *windowOrWidgetToTag, QWindow *mainWindow)
     

该函数为窗口系统设置一个提示,使其不将给定的QWindow或QWidget窗口实例化为主窗口,而是将其实例化为主窗口的子窗口。


参数说明:

  • windowOrWidgetToTag:要标记为子窗口的QObject(必须是QWindow或QWidget)

  • mainWindow:指定的父主窗


3.2 辅助函数








// 标记窗口为主窗口
static void QOhosFunctions::tagWindowOrWidgetAsMainWindow(QObject *windowOrWidgetToTag, bool forceMainWindow = true)
// 获取通过tagWindowOrWidgetAsSubWindowOf标记的父窗口指针。
static QWindow *QOhosFunctions::getWindowOrWidgetAsSubWindowOfTagValue(QObject *targetWindowOrWidget)
     


4

重要注意事项

⚠️ 警告:

  1. 在调用标记函数之前调 winId() 或 show() 会导致标签无效。

  2. mainWindow 必须是一个有效的 QWindow 指针。

  3. 如果 mainWindow 指向一个有效的QWindow,但这个QWindow不是主窗口,Qt框架会启用自动fallback机制,尝试找到合适的主窗口作为所有者。如果找不到合适的主窗口,就会创建一个主窗口而不是子窗口。


5

代码示例

5.1 基本用法








#include <QtPlatformHeaders/QOhosFunctions>
// 创建一个子窗口,指定它属于当前这个主窗口m_subwindow = new QWidget();QOhosFunctions::tagWindowOrWidgetAsSubWindowOf(m_subwindow, this->windowHandle());m_subwindow->resize(800600);m_subwindow->show();
   


5.2 对话框示例








// 方式1:使用Transient Parent(推荐)QDialog *dialog = new QDialog(this);  // this是主窗口widgetdialog->exec();  // 无需额外标记// 方式2:手动标记QDialog *dialog = new QDialog();QOhosFunctions::tagWindowOrWidgetAsSubWindowOf(dialog, this->windowHandle());dialog->exec();
     


5.3 多窗口应用示例



















class MainWindow : public QMainWindow{public:    void createSubWindow() {        // 创建子窗口        QWidget *subWindow = new QWidget();        // 标记为当前主窗口的子窗口        QOhosFunctions::tagWindowOrWidgetAsSubWindowOf(subWindow, this->windowHandle());        subWindow->setWindowTitle("子窗口");        subWindow->resize(400300);        subWindow->show();    }    void createNewMainWindow() {        // 创建新的主窗口(无需特殊标记)        MainWindow *newMainWindow = new MainWindow();        newMainWindow->show();    }};
     


6

最佳实践

  • 及时标记:在调用show()winId()之前完成窗口标记

  • 合理分类:明确区分哪些窗口应该是主窗口,哪些应该是子窗口

  • 利用Transient Parent:对于对话框等临时窗口,优先使用Qt原生的parent机制

  • 测试验证:HarmonyOS设备上验证窗口的层级关系和生命周期行为

  • 错误处理:考虑父窗口无效时的fallback行为


7

常见问题

Q

为什么我的子窗口显示为主窗口?

A

可能的原因:

在调用 show() 之后才调用标记函数

传入的 mainWindow 参数无效

忘记调用标记函数

Q

子窗口可以脱离主窗口独立存在吗?

A

不可以。在HarmonyOS中,子窗口必须依附于主窗口,主窗口关闭时子窗口会自动关闭。

Q

如何确认窗口的父子关系是否正确?

A

可以使用 QOhosFunctions::getWindowOrWidgetAsSubWindowOfTagValue() 函数查询窗口的标记状态。

来源:IFD优飞迪
二次开发电子云计算数字孪生试验
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2025-12-27
最近编辑:8月前
优飞迪科技
赋能新仿真,创优新设计
获赞 323粉丝 349文章 520课程 4
点赞
收藏
作者推荐
未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习计划 福利任务
下载APP
联系我们
帮助与反馈