Qt for HarmonyOS/user development/application lifecycle guide zh: Difference between revisions
No edit summary Tag: Manual revert |
No edit summary |
||
| Line 199: | Line 199: | ||
= 应用退出 = | = 应用退出 = | ||
=== | === 窗口关闭拦截 === | ||
HarmonyOS 平台提供了多层级的关闭拦截机制,Qt 通过完整的窗口关闭事件拦截系统,支持应用在不同关闭场景下进行自定义处理。本指南将详细说明该功能的实现机制、使用方法,并提供完整的代码示例。 | |||
Qt for HarmonyOS 实现了完整的窗口关闭事件拦截机制,适配 HarmonyOS 系统的三种等级预关闭系统: | |||
==== 关闭拦截层级架构 ==== | |||
HarmonyOS 系统提供了三个层级的拦截机制,Qt for HarmonyOS 目前支持前两个层级: | |||
1. '''Level 1: 窗口级别拦截''' | |||
* 用户点击窗口关闭按钮时触发 | |||
* 支持完全用户交互,可显示保存对话框 | |||
* 用户可选择取消关闭 | |||
2. '''Level 2: Ability级别拦截''' | |||
* 任务中心/Dock缩略图关闭时触发 | |||
* 支持快速保存操作 | |||
* 时间有限,建议快速处理 | |||
3. '''Level 3: AbilityStage级别拦截''' | |||
* 当前暂未支持 | |||
* 理论上用于最高优先级的系统级关闭 | |||
* 实际场景会降级到Level 2处理 | |||
==== 关闭方式与拦截等级对应关系 ==== | |||
{| class="wikitable" | |||
|+ | |||
!关闭方式 | |||
!拦截等级 | |||
!应用拦截行为 | |||
!系统API | |||
|- | |||
|主窗口关闭按钮 | |||
|Level 1 | |||
|完全交互:关闭/隐藏/最小化 | |||
|window.onWindowWillClose | |||
|- | |||
|子窗口关闭按钮 | |||
|Level 1 | |||
|完全交互:关闭/隐藏 | |||
|window.onWindowWillClose | |||
|- | |||
|任务中心/Dock缩略图 | |||
|Level 2 | |||
|快速保存:关闭/隐藏/最小化 | |||
|ability.onPrepareToTerminate | |||
|- | |||
|Dock右键菜单 | |||
|Level 2/3 | |||
|1.直接退出或 | |||
2.自动保存并退出 | |||
|abilityStage.onPrepareToTerminate暂不支持 | |||
降级到ability.onPrepareToTerminate | |||
|- | |||
|系统托盘关闭 | |||
|Level 2/3 | |||
|1.直接退出或 | |||
2.自动保存并退出 | |||
|abilityStage.onPrepareToTerminate暂不支持 | |||
降级到ability.onPrepareToTerminate | |||
|- | |||
|系统关机 | |||
|Level 2/3 | |||
|1.直接退出或 | |||
2.自动保存并退出 | |||
|abilityStage.onPrepareToTerminate暂不支持 | |||
降级到ability.onPrepareToTerminate | |||
|- | |||
|任务管理器强杀 | |||
| - | |||
|不支持拦截 | |||
| - | |||
|} | |||
==== Qt API 详解 ==== | |||
===== 关闭事件上下文系统 ===== | |||
Qt for HarmonyOS 通过关闭事件上下文系统来区分不同的关闭来源: | |||
# QOhosCloseEventContext - 关闭事件上下文管理器 | |||
# QCloseEvent扩展 - 在HarmonyOS平台添加了上下文成员 | |||
# QtOhosExtras公共API - 提供给开发者的接口 | |||
====== 关闭原因枚举 ====== | |||
<syntaxhighlight lang="cpp-qt"> | |||
// QtOhosExtras 公共API枚举 | |||
namespace QtOhosExtras { | |||
enum class CloseEventRootCause { | |||
InternalClose, // 内部关闭(应用程序化调用close()) | |||
AbilityClose, // Ability关闭(任务中心/Dock缩略图) | |||
WindowStageClose, // Window关闭(窗口关闭按钮) | |||
}; | |||
} | |||
</syntaxhighlight> | |||
====== 获取关闭事件原因API ====== | |||
<syntaxhighlight lang="cpp-qt"> | |||
// 获取关闭事件根本原因的API | |||
QtOhosExtras::CloseEventRootCause QtOhosExtras::getCloseEventRootCause(QCloseEvent *event); | |||
</syntaxhighlight>'''参数详解''' | |||
{| class="wikitable" | |||
|+ | |||
!参数 | |||
!类型 | |||
!说明 | |||
|- | |||
!event | |||
!QCloseEvent* | |||
!Qt关闭事件对象指针 | |||
|} | |||
'''返回值说明''' | |||
{| class="wikitable" | |||
|+ | |||
!返回值 | |||
!含义 | |||
!触发场景 | |||
|- | |||
!InternalClose | |||
!内部关闭 | |||
!应用调用`close()`、程序逻辑关闭 | |||
|- | |||
|WindowStageClose | |||
|窗口级关闭(Level 1) | |||
|用户点击窗口关闭按钮 | |||
|- | |||
!AbilityClose | |||
!Ability级关闭 (level 2) | |||
!任务中心、Dock缩略图关闭 | |||
|} | |||
==== 开发实现 ==== | |||
实现关闭拦截功能的关键在于:'''重写 closeEvent() 函数并根据关闭原因进行不同处理''' | |||
'''1. 简单的关闭拦截'''<syntaxhighlight lang="cpp-qt"> | |||
#include <QtOhosExtras/QtOhosExtras> | |||
#include <QCloseEvent> | |||
#include <QMessageBox> | |||
class MyMainWindow : public QMainWindow { | |||
protected: | |||
void closeEvent(QCloseEvent *event) override { | |||
// 获取关闭事件的原因 | |||
auto rootCause = QtOhosExtras::getCloseEventRootCause(event); | |||
switch (rootCause) { | |||
case QtOhosExtras::CloseEventRootCause::WindowStageClose: | |||
// 用户点击关闭按钮 | |||
handleWindowClose(event); | |||
break; | |||
case QtOhosExtras::CloseEventRootCause::AbilityClose: | |||
// 任务中心关闭 | |||
handleAbilityClose(event); | |||
break; | |||
case QtOhosExtras::CloseEventRootCause::InternalClose: | |||
// 程序内部关闭 | |||
event->accept(); | |||
break; | |||
} | |||
} | |||
private: | |||
void handleWindowClose(QCloseEvent *event) { | |||
// 窗口关闭按钮:可以显示对话框 | |||
if (hasUnsavedData()) { | |||
int ret = QMessageBox::question(this, "确认关闭", | |||
"有未保存的数据,是否保存?", | |||
QMessageBox::Save | | |||
QMessageBox::Discard | | |||
QMessageBox::Cancel); | |||
if (ret == QMessageBox::Save) { | |||
saveData(); | |||
event->accept(); | |||
} else if (ret == QMessageBox::Discard) { | |||
event->accept(); | |||
} else { | |||
event->ignore(); // 取消关闭 | |||
} | |||
} else { | |||
event->accept(); | |||
} | |||
} | |||
void handleAbilityClose(QCloseEvent *event) { | |||
// 任务中心关闭:快速处理 | |||
if (hasUnsavedData()) { | |||
saveData(); // 自动保存 | |||
} | |||
event->accept(); | |||
} | |||
bool hasUnsavedData() const { | |||
// 检查是否有未保存数据 | |||
return m_hasUnsavedData; | |||
} | |||
void saveData() { | |||
// 保存数据 | |||
m_hasUnsavedData = false; | |||
} | |||
private: | |||
bool m_hasUnsavedData = false; | |||
}; | |||
</syntaxhighlight>'''2. 项目配置'''<syntaxhighlight lang="text"> | |||
# 项目配置文件 | |||
QT += core gui widgets ohosextras | |||
SOURCES += main.cpp mainwindow.cpp | |||
HEADERS += mainwindow.h | |||
</syntaxhighlight>'''QT += ohosextras''':必须添加此模块以使用关闭拦截API | |||
==== 适用场景 ==== | |||
* 文档编辑器:Word、Excel等需要保存确认的应用 | |||
* 代码编辑器:IDE、代码编辑器等开发工具 | |||
* 图形设计软件:Photoshop类应用,防止意外丢失工作 | |||
* 数据库管理工具:需要确保数据完整性的应用 | |||
* 媒体编辑应用:视频、音频编辑器等长时间工作的应用 | |||
==== 开发注意事项 ==== | |||
'''Level 3拦截支持状态''' | |||
当前状态:Level 3拦截(`abilityStage.onPrepareToTerminate`)暂未支持 | |||
影响场景:系统关机、Dock右键菜单、系统托盘关闭等 | |||
实际行为:这些场景可能会触发Level 2拦截(`ability.onPrepareToTerminate`),表现为`AbilityClose`事件 | |||
使用建议 | |||
* 1. **窗口关闭**:可以显示完整的保存对话框 2. **任务中心关闭**:建议快速自动保存,避免耗时操作 3. **系统级关闭**:系统关机、Dock右键菜单等场景可能触发`AbilityClose`事件,应妥善处理 4. **测试验证**:在不同关闭方式下测试,确保应用能正确响应 | |||
Revision as of 06:58, 14 November 2025
中文 English
先导知识
鸿蒙应用生命周期相关文档:
Qt for HarmonyOS应用生命周期概述
在鸿蒙系统中,应用生命周期管理遵循Stage模型,主要包括UIAbility组件的生命周期管理。Qt for HarmonyOS应用作为鸿蒙生态的一部分,同样需要适配这一生命周期模型。
Qt for HarmonyOS应用的生命周期主要涉及以下几个方面:
1. 应用启动与初始化
2. 应用间交互(拉起其他应用/被其他应用拉起)
3. 多实例管理
4. 应用退出
应用启动与初始化
在Qt for HarmonyOS中,应用启动流程是由系统自动管理的,开发者无需关心底层细节。实际流程如下:
1. 系统启动鸿蒙Stage模型下的UIAbility组件
2. UIAbility组件通过NAPI方式调用启动Qt线程
3. 系统自动加载Qt应用的共享库,并调用Qt应用的main函数
4. Qt应用的主窗口被创建并显示在HarmonyOS的WindowStage中
对开发者来说,应用的入口仍然是main函数,无需关注更多细节。
应用间交互(拉起其他应用/被其他应用拉起)
在Qt for HarmonyOS中,可以使用QtOhosExtras模块提供的API (startAbility)来拉起其他应用,替代传统Qt中的QProcess方案。
注意:下面的方法只能拉起带界面应用。
拉起其他应用
显式匹配(指定包名和Ability名)
#include <QtOhosExtras/qohoswant.h>
#include <QtOhosExtras/qohosuiabilitycontext.h>
void MainWindow::startSpecificApp()
{
QtOhosExtras::QOhosWant want;
want.bundleName = "com.example.targetapp"; // 目标应用的包名
want.abilityName = "MainAbility"; // 目标应用的Ability名称
// 可选:传递参数
QJsonObject parameters;
parameters.insert("key", "value");
want.parameters = parameters;
// 启动目标应用
QtOhosExtras::startAbility(want);
}
隐式匹配(通过action和uri匹配)
void MainWindow::startAppByAction()
{
QtOhosExtras::QOhosWant want;
want.action = "ohos.want.action.viewData"; // 操作类型
want.type = "text/plain"; // 数据类型
want.uri = "content://example/data"; // 数据URI
// 可选:传递参数
QJsonObject parameters;
parameters.insert("key", "value");
want.parameters = parameters;
// 启动匹配的应用
QtOhosExtras::startAbility(want);
}
被其他应用拉起
当Qt应用被其他应用拉起时,需要处理接收到的Want参数。
在模块的module.json5里面配置如下:
"abilities": [
{
"name": "QAbility",
"srcEntry": "./ets/qability/QAbility.ets",
"launchType": "specified",
"description": "$string:QAbility_desc",
"icon": "$media:icon",
"label": "$string:QAbility_label",
"startWindowIcon": "$media:icon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home",
"ohos.want.action.viewData" // 支持的action类型
],
"uris": [{"type": "*/*"}] // 支持的数据类型
}
]
}
]
处理接收到的Want
#include <QtOhosExtras/QtOhosExtras>
void MainWindow::init()
{
// 连接Want接收信号
QObject::connect(
QtOhosExtras::QOhosUiAbilityContext::instance(),
&QtOhosExtras::QOhosUiAbilityContext::newWantReceived,
this,
&MainWindow::onNewWantReceived
);
}
void MainWindow::onNewWantReceived(QtOhosExtras::QOhosWant want)
{
// 处理接收到的Want参数
qDebug() << "Received want with action:" << want.action;
qDebug() << "URI:" << want.uri;
qDebug() << "Type:" << want.type;
// 处理参数
if (want.parameters.contains("key")) {
QString value = want.parameters.value("key").toString();
processParameter(value);
}
// 根据Want内容执行相应操作
if (want.action == "ohos.want.action.viewData") {
openDataForViewing(want.uri);
}
}
多实例管理
在HarmonyOS系统中,应用可以有多种实例模式:单实例、多实例单进程、多实例多进程。Qt for HarmonyOS应用需要根据需求选择合适的模式。
注意:这里的实例指的是UIAbility实例。
单实例模式
当应用被再次拉起时,使用现有实例处理新的请求:
void MainWindow::onNewWantReceived(QtOhosExtras::QOhosWant want)
{
// 使用现有窗口处理新请求
processNewRequest(want);
this->setText(want.uri); // 单实例单进程:原窗口处理
}
多实例单进程模式
每次被拉起时创建新的UIAbility实例,但共享同一进程:
void MainWindow::onNewWantReceived(QtOhosExtras::QOhosWant want)
{
// 创建新窗口实例
MainWindow *newWindow = new MainWindow();
newWindow->processRequest(want);
newWindow->show();
}
多实例多进程模式
启动新的应用进程创建新的UIAbility实例处理请求:
void MainWindow::onNewWantReceived(QtOhosExtras::QOhosWant want)
{
// 启动新进程
static int processCounter = 0;
QString processName = "Process" + QString::number(processCounter++);
// 使用QtOhosExtras启动新进程
QtHarmonyOSExtras::startAppProcess(processName, want);
}
注意:多实例多进程模式需要在module.json5中添加配置:
"abilities": [
{
"name": "QAbility",
// 其他配置...
"isolationProcess": true
}
]
应用退出
窗口关闭拦截
HarmonyOS 平台提供了多层级的关闭拦截机制,Qt 通过完整的窗口关闭事件拦截系统,支持应用在不同关闭场景下进行自定义处理。本指南将详细说明该功能的实现机制、使用方法,并提供完整的代码示例。
Qt for HarmonyOS 实现了完整的窗口关闭事件拦截机制,适配 HarmonyOS 系统的三种等级预关闭系统:
关闭拦截层级架构
HarmonyOS 系统提供了三个层级的拦截机制,Qt for HarmonyOS 目前支持前两个层级:
1. Level 1: 窗口级别拦截
- 用户点击窗口关闭按钮时触发
- 支持完全用户交互,可显示保存对话框
- 用户可选择取消关闭
2. Level 2: Ability级别拦截
- 任务中心/Dock缩略图关闭时触发
- 支持快速保存操作
- 时间有限,建议快速处理
3. Level 3: AbilityStage级别拦截
- 当前暂未支持
- 理论上用于最高优先级的系统级关闭
- 实际场景会降级到Level 2处理
关闭方式与拦截等级对应关系
| 关闭方式 | 拦截等级 | 应用拦截行为 | 系统API |
|---|---|---|---|
| 主窗口关闭按钮 | Level 1 | 完全交互:关闭/隐藏/最小化 | window.onWindowWillClose |
| 子窗口关闭按钮 | Level 1 | 完全交互:关闭/隐藏 | window.onWindowWillClose |
| 任务中心/Dock缩略图 | Level 2 | 快速保存:关闭/隐藏/最小化 | ability.onPrepareToTerminate |
| Dock右键菜单 | Level 2/3 | 1.直接退出或
2.自动保存并退出 |
abilityStage.onPrepareToTerminate暂不支持
降级到ability.onPrepareToTerminate |
| 系统托盘关闭 | Level 2/3 | 1.直接退出或
2.自动保存并退出 |
abilityStage.onPrepareToTerminate暂不支持
降级到ability.onPrepareToTerminate |
| 系统关机 | Level 2/3 | 1.直接退出或
2.自动保存并退出 |
abilityStage.onPrepareToTerminate暂不支持
降级到ability.onPrepareToTerminate |
| 任务管理器强杀 | - | 不支持拦截 | - |
Qt API 详解
关闭事件上下文系统
Qt for HarmonyOS 通过关闭事件上下文系统来区分不同的关闭来源:
- QOhosCloseEventContext - 关闭事件上下文管理器
- QCloseEvent扩展 - 在HarmonyOS平台添加了上下文成员
- QtOhosExtras公共API - 提供给开发者的接口
关闭原因枚举
// QtOhosExtras 公共API枚举
namespace QtOhosExtras {
enum class CloseEventRootCause {
InternalClose, // 内部关闭(应用程序化调用close())
AbilityClose, // Ability关闭(任务中心/Dock缩略图)
WindowStageClose, // Window关闭(窗口关闭按钮)
};
}
获取关闭事件原因API
// 获取关闭事件根本原因的API
QtOhosExtras::CloseEventRootCause QtOhosExtras::getCloseEventRootCause(QCloseEvent *event);
参数详解
| 参数 | 类型 | 说明 |
|---|---|---|
| event | QCloseEvent* | Qt关闭事件对象指针 |
返回值说明
| 返回值 | 含义 | 触发场景 |
|---|---|---|
| InternalClose | 内部关闭 | 应用调用`close()`、程序逻辑关闭 |
| WindowStageClose | 窗口级关闭(Level 1) | 用户点击窗口关闭按钮 |
| AbilityClose | Ability级关闭 (level 2) | 任务中心、Dock缩略图关闭 |
开发实现
实现关闭拦截功能的关键在于:重写 closeEvent() 函数并根据关闭原因进行不同处理
1. 简单的关闭拦截
#include <QtOhosExtras/QtOhosExtras>
#include <QCloseEvent>
#include <QMessageBox>
class MyMainWindow : public QMainWindow {
protected:
void closeEvent(QCloseEvent *event) override {
// 获取关闭事件的原因
auto rootCause = QtOhosExtras::getCloseEventRootCause(event);
switch (rootCause) {
case QtOhosExtras::CloseEventRootCause::WindowStageClose:
// 用户点击关闭按钮
handleWindowClose(event);
break;
case QtOhosExtras::CloseEventRootCause::AbilityClose:
// 任务中心关闭
handleAbilityClose(event);
break;
case QtOhosExtras::CloseEventRootCause::InternalClose:
// 程序内部关闭
event->accept();
break;
}
}
private:
void handleWindowClose(QCloseEvent *event) {
// 窗口关闭按钮:可以显示对话框
if (hasUnsavedData()) {
int ret = QMessageBox::question(this, "确认关闭",
"有未保存的数据,是否保存?",
QMessageBox::Save |
QMessageBox::Discard |
QMessageBox::Cancel);
if (ret == QMessageBox::Save) {
saveData();
event->accept();
} else if (ret == QMessageBox::Discard) {
event->accept();
} else {
event->ignore(); // 取消关闭
}
} else {
event->accept();
}
}
void handleAbilityClose(QCloseEvent *event) {
// 任务中心关闭:快速处理
if (hasUnsavedData()) {
saveData(); // 自动保存
}
event->accept();
}
bool hasUnsavedData() const {
// 检查是否有未保存数据
return m_hasUnsavedData;
}
void saveData() {
// 保存数据
m_hasUnsavedData = false;
}
private:
bool m_hasUnsavedData = false;
};
2. 项目配置
# 项目配置文件
QT += core gui widgets ohosextras
SOURCES += main.cpp mainwindow.cpp
HEADERS += mainwindow.h
QT += ohosextras:必须添加此模块以使用关闭拦截API
适用场景
- 文档编辑器:Word、Excel等需要保存确认的应用
- 代码编辑器:IDE、代码编辑器等开发工具
- 图形设计软件:Photoshop类应用,防止意外丢失工作
- 数据库管理工具:需要确保数据完整性的应用
- 媒体编辑应用:视频、音频编辑器等长时间工作的应用
开发注意事项
Level 3拦截支持状态
当前状态:Level 3拦截(`abilityStage.onPrepareToTerminate`)暂未支持
影响场景:系统关机、Dock右键菜单、系统托盘关闭等
实际行为:这些场景可能会触发Level 2拦截(`ability.onPrepareToTerminate`),表现为`AbilityClose`事件
使用建议
- 1. **窗口关闭**:可以显示完整的保存对话框 2. **任务中心关闭**:建议快速自动保存,避免耗时操作 3. **系统级关闭**:系统关机、Dock右键菜单等场景可能触发`AbilityClose`事件,应妥善处理 4. **测试验证**:在不同关闭方式下测试,确保应用能正确响应