HarmonyOS 鸿蒙Next中任务栏关闭子窗口导致程序被关闭

HarmonyOS 鸿蒙Next中任务栏关闭子窗口导致程序被关闭

Qt框架的一个程序。

通过菜单会创建一个没有父类的子窗口A用于显示一些内存之类的统计信息。

module.json5中launchType如果设置为singleton,这个子窗口不能被打开,因此当前用的是standard。

"abilities": [
  {
    "name": "EntryAbility",
    "launchType": "standard",
    ...
  }
],
  1. 在主窗口和子窗口A都存在的情况下,鼠标浮动在任务栏(Dock栏)显示出浏览窗口,此时浏览窗口会有显示主窗口和子窗口A,并且浏览窗口右上角都有各自的关闭按钮。

  2. 子窗口A并没有对关闭事件做什么特别处理,在closeEvent中存了窗口的geometry,然后调用QWidget::closeEvent(event)传出去了。

  3. 点击子窗口A的浏览窗口的关闭按钮关闭子窗口A,A先被关闭,然后主窗口也被关闭程序退出。

  4. 如果存在多个没有父类的子窗口,打开不同类型的A窗口和B窗口,关闭B窗口,从日志来看只打印了B窗口的closeEvent()中的日志,A窗口和主窗口的closeEvent()未触发,但程序结束所有窗口消失。

  5. 如果直接从子窗口A的界面的关闭按钮关闭,不会出现这个问题。

如果我把QWidget::closeEvent(event)替换成

event->ignore();
  1. 子窗口右上角关闭按钮失效。

  2. 在任务栏浏览窗口可以正常关掉子窗口A,但是我不能重新打开,因为修改后,再次触发按钮,指针判断不为空,但是调用show之后子窗口A显示不出来:

void Basic::on_stats_triggered()
{
        if (!stats.isNull()) {
               stats->show();
               stats->raise();
               return;
        }
        BasicStats *statsDlg = new BasicStats();
        statsDlg->show();
        stats = statsDlg;
        QScreen* targetScreen = this->screen();
        QRect geometry = targetScreen->geometry();
        statsDlg->move(geometry.center() - QPoint(statsDlg->width()/2, statsDlg->height()/1.5));
}

更多关于HarmonyOS 鸿蒙Next中任务栏关闭子窗口导致程序被关闭的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

在HarmonyOS Next中,任务栏关闭子窗口导致主程序关闭是设计行为。当使用多窗口功能时,子窗口与主应用共享同一进程,关闭最后一个子窗口会触发整个应用退出。这是鸿蒙多窗口管理机制决定的,不同于传统桌面系统的窗口独立管理模式。开发者可通过在config.json中配置"continuable"为true来改变此行为,使应用在关闭所有窗口后仍保持后台运行。该特性适用于需要持久化运行的应用场景。

更多关于HarmonyOS 鸿蒙Next中任务栏关闭子窗口导致程序被关闭的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


这是一个典型的窗口生命周期管理问题。在HarmonyOS Next中,当使用standard启动模式时,系统会将每个窗口视为独立实例。您遇到的问题是Qt子窗口关闭时意外终止了整个应用进程。

根本原因分析:

  1. 当从任务栏关闭无父窗口的子窗口时,系统可能错误地将此操作传播到整个应用进程
  2. 您使用的指针判断方式(!stats.isNull())存在问题,因为窗口被关闭后指针可能非空但已失效

建议解决方案:

  1. 修改窗口创建逻辑,确保子窗口有正确的父窗口关联
  2. 使用QPointer代替原始指针进行窗口有效性判断
  3. 在closeEvent中添加对窗口关闭来源的判断,区分任务栏关闭和正常关闭

关键代码修改建议:

// 使用QPointer管理窗口
QPointer<BasicStats> stats;

void Basic::on_stats_triggered()
{
    if (stats && stats->isVisible()) {
        stats->raise();
        return;
    }
    
    stats = new BasicStats(this); // 明确指定父窗口
    // ...其余初始化代码
}

// 在BasicStats中重写closeEvent
void BasicStats::closeEvent(QCloseEvent *event)
{
    // 保存geometry等操作
    QWidget::closeEvent(event);
}

这种修改可以确保:

  1. 窗口关闭行为符合预期
  2. 从任务栏关闭子窗口不会影响主窗口
  3. 窗口可以正常重新打开,
回到顶部