2015-10-16 5 views
2

Мой опыт работы в Qt составляет около двух недель, извините, если я случайно задаюсь глупым вопросом.QtQuick: как переопределить событие закрытия окна?

В моей программе используется графический интерфейс на основе QtQuick. Я отформатируйте ее в моем 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 , Но это не публика, у меня нет доступа к ее методам!

Ok. Другой способ может заключаться в том, что я мог бы сделать что-то подобное из QML. QML тип QWindow имеет closing(CloseEvent) сигнал, и если я установил CloseEvent.accepted false в слот, подключенный к нему, который предотвратит немедленное закрытие окна и позволит мне вызвать метод veryVeryImportantItem.cleanup(). Но тогда у меня есть другая проблема: как мне получить ссылку на мое корневое окно, если я создал его не в QML, а в стартовом коде C++.

Я думаю, что это очень распространенная ситуация, и, очевидно, должен быть четко определенный способ справиться с этим, но я уже четыре часа работаю в поисковых системах и до сих пор не нашел достойного объяснения.

+0

VeryVeryImportantItem деструктор вызывается при закрытии окна. Вы можете сделать любую очистку здесь. – Meefte

+0

Ну, я это знаю. Но это не подходит моему делу. Моя архитектура требует некоторого обмена сигналами, чтобы выполнить очистку. – krokoziabla

ответ

4

Я думаю, это очень распространенная ситуация, и, очевидно, должно быть хорошо определен способ справиться с этим

Да, можно было бы сказать, что.

Проще всего было бы переключиться на использование 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() 
    } 
} 
+0

Как можно задержать закрытие вопросом вроде «вы уверены ...?» используя modal 'Dialog'? Кажется, это невозможно в императивном стиле без дополнительного свойства логического флага. – Orient

+0

@Orient - просто добавьте 'свойство bool canExit', а затем в закрытое событие' close.accepted = true или false' в зависимости от ваших требований. – dtech

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); 
    } 
}; 

на главном, например, ваш новый класс:

NewQuickView quickView(QUrl("MyView.qml")); 
Смежные вопросы