QtQuick:如何覆盖窗口关闭事件?

Posted

技术标签:

【中文标题】QtQuick:如何覆盖窗口关闭事件?【英文标题】:QtQuick: how to override window close event? 【发布时间】:2015-10-16 13:53:44 【问题描述】:

我在 Qt 的经验大约是两周,如果我碰巧问了一个愚蠢的问题,请原谅。

我的程序使用基于 QtQuick 的 GUI。我在我的 main.cpp

中初始化它
#include <QGuiApplication>
#include <QtQuick/QQuickView>

#include "VeryVeryImportantItem.h"

extern
int main(int argc, char * argv[])

    qmlRegisterType<VeryVeryImportantItem>("com.my.stuff", 1, 0, "VeryVeryImportantItem");

    QQuickView      quickView(QUrl("MyView.qml"));

    quickView.show();

    QGuiApplication app;

    return app.exec();

MyView.qml 看起来像这样:

import QtQuick 2.1
import QtQuick.Window 2.1
import com.my.stuff 1.0

Item VeryVeryImportantItem 
    id : veryVeryImportantItem
    ...

VeryVeryImportantItem.h如下:

#include <QtQuick/QQuickItem>

class VeryVeryImportantItem : public QQuickItem

    Q_OBJECT
public:
    Q_INVOKABLE void cleanup();
    ...
;

现在问题来了。 如何在我的根窗口/视图上拦截关闭事件,调用 VeryVeryImportantItem::cleanup();并且只有在那之后关闭应用程序?

我现在发现的是 QQuickItem::window() 可以给我指向我需要的窗口的指针,并且窗口有信号 QQuickWindow::closing(QQuickCloseEvent *); 并且理论上我可以通过操作给定的来防止窗口关闭QQuickCloseEvent 对象。 但它不是公开的,我无权访问它的方法!

好的。另一种方法可能是我可以从 QML 做类似的事情。 QML 类型QWindow 具有closing(CloseEvent) 信号,如果我在与其连接的插槽中设置CloseEvent.accepted false,这将阻止窗口立即关闭并使我能够调用veryVeryImportantItem.cleanup() 方法。但是我有另一个问题:如果我不是在 QML 中而是在 C++ 启动代码中创建它,我如何获得对我的根窗口的引用。

我想这是很常见的情况,显然应该有一个明确的方法来处理这个问题,但我已经用谷歌搜索了大约四个小时,仍然没有找到任何合适的解释。

【问题讨论】:

VeryVeryImportantItem 析构函数在您关闭窗口时被调用。您可以在这里进行任何清理。 嗯,我知道。但这不适合我的情况。我的架构需要一些信号交换才能完成清理。 【参考方案1】:

我想这是很常见的情况,显然应该 是一个明确的方式来处理这个

是的,可以这么说。

最简单的做法是切换到使用 QQmlApplicationEngine 并在 QML 端使用 ApplicationWindow 作为根组件。

然后您可以简单地使用onClosing 信号处理程序来运行您的清理。我有一个类似的场景,如果在调用清理之前关闭应用程序会崩溃,而这种方法完美无缺。

//main.cpp
QQmlApplicationEngine engine;
engine.load(QUrl("MyView.qml"));

.

ApplicationWindow 
    visible: true
    width: 1280
    height: 720    

    BoxView 
        id: view
    

    onClosing: 
        view.deleteView()
    

【讨论】:

如何才能延迟关闭诸如“你确定...?”之类的问题。使用模态Dialog?如果没有额外的布尔标志属性,在命令式风格中似乎是不可能的。 @Orient - 只需添加一个property bool canExit,然后根据您的要求在关闭事件中添加close.accepted = true or false【参考方案2】:

您可以在 QQuickView 上拦截关闭事件。为此,请创建一个派生类并覆盖事件方法:

class NewQuickView: public QQuickView 
public:
    NewQuickView(QUrl url):
        QQuickView(url) 
public:
    bool event(QEvent *event) override
    
        if (event->type() == QEvent::Close) 
            // your code here
        
        return QQuickView::event(event);
    
;

在 main 上,实例化你的新类:

NewQuickView quickView(QUrl("MyView.qml"));

【讨论】:

以上是关于QtQuick:如何覆盖窗口关闭事件?的主要内容,如果未能解决你的问题,请参考以下文章

QMLHelloWorld

Python TKinter 事件 - 关闭窗口 [重复]

如何更改 QtQuick 2 窗口的标题?

QtQuick2 无法将 ApplicationWindow 关闭信号连接到方法(C++ 新手)

单击窗口外覆盖时如何关闭 Kendo UI 模态窗口?

关闭 Chrome 窗口未在卸载事件处理程序中使用 sendBeacon 发送数据