Деструктор типа С++ не вызывается в QML

Я создаю приложение Sailfish (используя последнюю версию Sailfish SDK). У меня проблема с представлением объекта C++ в QML. Он наследует QSettings,

class Settings : public QSettings
{
    Q_OBJECT
    /**/
public:
    explicit Settings() : QSettings("Marcin Mielniczuk", "BigText") {}
    ~Settings() { qDebug() << "Dying"; }

    /**/
};

Я заметил, что деструктор вообще не вызывается. (нет вывода деструктора)

Я создаю объект следующим образом:

import QtQuick 2.0
import Sailfish.Silica 1.0
import BigText 1.0
import "pages"

ApplicationWindow
{
    initialPage: MainPage { }
    Settings {id: settings}
}

Мой main.cpp:

Q_DECL_EXPORT int main(int argc, char *argv[])
{
    QScopedPointer<QGuiApplication> app(Sailfish::createApplication(argc, argv));

    qmlRegisterType<Settings>("BigText", 1, 0, "Settings");

    QScopedPointer<QQuickView> view(Sailfish::createView("main.qml"));

    Sailfish::showView(view.data());

    return app->exec();
}

Что я делаю не так?

/edit: текст, который не печатается, не является реальной проблемой - это просто индикатор проблемы. Синхронизация QSettings в деструкторе тоже не работает.

EDIT2: обратите внимание, что ApplicationWindow в я использую Sailfish Silica, а не QtQuick.Controls, и окно отображается нормально. Эти компоненты должны несколько отличаться от стандартных компонентов qt quick.


person marmistrz    schedule 03.09.2013    source источник
comment
Является ли деструктор QSettings виртуальным?   -  person doctorlove    schedule 03.09.2013
comment
Измените qDebug на std::cout, я думаю, qDebug может использовать цикл обработки событий...   -  person UldisK    schedule 03.09.2013
comment
Безуспешно, но это все равно не решит проблему - синхронизация QSettings в деструкторе тоже не работает... (даже без явного деструктора)   -  person marmistrz    schedule 03.09.2013
comment
Doctorlove: Да, QSettings наследуется от QObject, чей деструктор виртуальный.   -  person Frank Osterfeld    schedule 05.09.2013
comment
Что ж, на самом деле ничего страшного. Посмотрите на мой ответ.   -  person marmistrz    schedule 08.09.2013


Ответы (4)


В вашей логике нет ничего изначально неправильного. Вот его упрощенная версия. Я могу запускать его локально и постоянно получать сообщение Dying на выходе каждый раз, когда окно закрывается и приложение завершает работу.

Если вы не можете понять это, я предлагаю преобразовать этот код в то, что вы делаете, пока он не выйдет из строя.

Между прочим, это, безусловно, всего лишь фрагмент чего-то большего, что вы делаете, но, по крайней мере, в этом примере эти указатели с областью видимости мало что делают.

main.qml

import QtQuick 2.0
import BigText 1.0

Item {
    width: 300; height: 300
    Settings {id: settings}
}

main.cpp

class Settings : public QSettings
{
    Q_OBJECT
    public:
    Settings() : QSettings("Marcin Mielniczuk", "BigText") {}
    ~Settings() { qDebug() << "Dying"; }

};

int main(int argc, char *argv[])
{
    QScopedPointer<QGuiApplication> app(new QGuiApplication(argc, argv));
    qmlRegisterType<Settings>("BigText", 1, 0, "Settings");
    QScopedPointer<QQuickView> view(new QQuickView());
    view->setSource(QUrl::fromLocalFile("main.qml"));
    view->show();
    return app->exec();
}
person Gustavo Niemeyer    schedule 03.09.2013
comment
Это работало, когда я делал так. Но как только я изменил Item на ApplicationWindow, он перестал работать... - person marmistrz; 04.09.2013
comment
Это никогда не сработает, потому что вы не можете использовать QQuickView с ApplicationWindow. Он даже не загружает основной компонент. - person Kuba hasn't forgotten Monica; 04.09.2013
comment
В Sailfish SDK есть Qt 5.0.2 (то есть, как написано в примечаниях к выпуску, почти 5.1). В остальном приложение работает нормально. Движок создан с помощью Sailfish::create. Он определен здесь: github.com/owncloud/News -Qt-App/blob/master/sailfishapplication/ - person marmistrz; 05.09.2013

Вы можете попробовать поместить и идентифицировать ваш ApplicationWindow и явно использовать метод destroy () в какое-то время и посмотреть, что произойдет.

person Qnoobish    schedule 04.09.2013
comment
ApplicationWindow должен быть неразрушимым. Я могу вручную уничтожить настройки, и все работает нормально. - person marmistrz; 07.09.2013

Вы не можете использовать QQuickView с классом ApplicationWindow. Не только ваш деструктор не вызывается, но и ваш конструктор не тоже, потому что загрузка никогда не завершается успешно.

Приведенный ниже код отлично работает в Qt 5.1.1. Протестировано как на OS X 10.8, так и на Windows 7.

main.qrc

<RCC>
  <qresource prefix="/">
    <file>main.qml</file>
  </qresource>
</RCC>

main.pro

QT       += core gui qml quick
TARGET = qml-appwin-end-18597527
TEMPLATE = app
SOURCES += main.cpp
OTHER_FILES += main.qml
RESOURCES += main.qrc

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QSettings>
#include <QQuickWindow>
#include <QtQml>
#include <QDebug>

class Settings : public QSettings
{
    Q_OBJECT
    public:
    Settings() : QSettings("Marcin Mielniczuk", "BigText") {}
    ~Settings() { qDebug() << "Dying"; }
};

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    qmlRegisterType<Settings>("BigText", 1, 0, "Settings");
    engine.load(QUrl("qrc:/main.qml"));
    QObject *topLevel = engine.rootObjects().value(0);
    QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
    window->show();
    return app.exec();
}

#include "main.moc"

main.qml

import QtQuick 2.0
import QtQuick.Controls 1.0
import BigText 1.0

ApplicationWindow {
    width: 300; height: 300
    Settings {id: settings}
}
person Kuba hasn't forgotten Monica    schedule 04.09.2013
comment
Кажется, что ApplicationWindow is Sailfish Silica несколько отличается, так как работает нормально, за исключением уничтожения дочерних объектов. Загрузка окна прошла успешно - person marmistrz; 07.09.2013

В моем коде нет ничего плохого. Это что-то с SDK. Отладка показывает

ASSERT: "QThread::currentThread() == QCoreApplication::instance()->thread()" in file debugger/qqmldebugserver.cpp, line 576

Затем программа прерывается, и поэтому деструктор не вызывается.

person marmistrz    schedule 08.09.2013