QtQuick:如何覆盖 window 关闭事件?
QtQuick: how to override window close event?
我在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();
...
};
现在是问题。 如何拦截我的根 window/view 上的关闭事件,调用 VeryVeryImportantItem::cleanup();然后才关闭应用程序?
我现在发现 QQuickItem::window()
可以给我指向我需要的 window 的指针,并且 window 有信号 QQuickWindow::closing(QQuickCloseEvent *);
并且理论上我可以通过操纵给定的 QQuickCloseEvent
对象来防止 window 关闭。 但它不是public,我无法访问它的方法!
好的。另一种方法可能是我可以从 QML 做类似的事情。 QML 类型 QWindow
有 closing(CloseEvent)
信号,如果我在与其连接的插槽中设置 CloseEvent.accepted
false 将阻止 window 立即关闭并使我能够调用 veryVeryImportantItem.cleanup()
方法。但后来我遇到了另一个问题:如果我不是在 QML 中而是在 C++ 启动代码中创建的,我如何获得对根 window 的引用。
我想这是很常见的情况,显然应该有一个明确的方法来处理这个问题,但我已经谷歌搜索了大约四个小时,但仍然没有找到任何合适的解释。
I guess this is the very common situation and there obviously ought to
be a well-defined way to handle this
是的,可以这么说。
最简单的方法是切换到使用 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()
}
}
您可以拦截QQuickView的关闭事件。为此,创建派生的 class 并覆盖事件方法:
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 上,例如你的新 class:
NewQuickView quickView(QUrl("MyView.qml"));
我在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();
...
};
现在是问题。 如何拦截我的根 window/view 上的关闭事件,调用 VeryVeryImportantItem::cleanup();然后才关闭应用程序?
我现在发现 QQuickItem::window()
可以给我指向我需要的 window 的指针,并且 window 有信号 QQuickWindow::closing(QQuickCloseEvent *);
并且理论上我可以通过操纵给定的 QQuickCloseEvent
对象来防止 window 关闭。 但它不是public,我无法访问它的方法!
好的。另一种方法可能是我可以从 QML 做类似的事情。 QML 类型 QWindow
有 closing(CloseEvent)
信号,如果我在与其连接的插槽中设置 CloseEvent.accepted
false 将阻止 window 立即关闭并使我能够调用 veryVeryImportantItem.cleanup()
方法。但后来我遇到了另一个问题:如果我不是在 QML 中而是在 C++ 启动代码中创建的,我如何获得对根 window 的引用。
我想这是很常见的情况,显然应该有一个明确的方法来处理这个问题,但我已经谷歌搜索了大约四个小时,但仍然没有找到任何合适的解释。
I guess this is the very common situation and there obviously ought to be a well-defined way to handle this
是的,可以这么说。
最简单的方法是切换到使用 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()
}
}
您可以拦截QQuickView的关闭事件。为此,创建派生的 class 并覆盖事件方法:
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 上,例如你的新 class:
NewQuickView quickView(QUrl("MyView.qml"));