Basé sur Qt la documentation chaque fois que a QObject Le type de pointeur est transmis du code C++ à QML, par l'intermédiaire d'un Q_INVOKABLE il existe un ensemble de règles qui déterminent qui est responsable de la durée de vie de ce pointeur. Si le pointeur QObject est sans parent, le moteur QML est implicitement responsable de la propriété du pointeur.
Dans mon scénario, je veux que mon interface utilisateur frontale représente un modèle de liste qui est généré/fourni par le code C++ du backend. Je suppose que le pointeur restera en vie tant que le code QML y fera référence. Le code ci-dessous montre le cas de test réduit :
Main.cpp
#include <QAbstractItemModel>
#include <QDebug>
#include <QGuiApplication>
#include <QObject>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QStringListModel>
class MyStringListModel : public QStringListModel
{
Q_OBJECT
public:
explicit MyStringListModel(const QStringList &strings, QObject* parent=nullptr) : QStringListModel(strings, parent)
{
qDebug() << "Creation";
}
virtual ~MyStringListModel() override
{
qDebug() << "Destruction";
}
};
class Backend : public QObject
{
Q_OBJECT
public:
Backend(QObject* parent=nullptr) : QObject(parent)
{
}
Q_INVOKABLE QAbstractItemModel* createModel() const
{
static const QStringList months = {
tr("January"),
tr("February"),
tr("March"),
tr("April"),
tr("May"),
tr("June"),
tr("July"),
tr("August"),
tr("September"),
tr("October"),
tr("November"),
tr("December"),
};
return new MyStringListModel(months);
}
};
int main(int argc, char* argv[])
{
QGuiApplication application(argc, argv);
qmlRegisterType<QAbstractItemModel>();
Backend backend;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("backend", &backend);
engine.load("qrc:///ui/main.qml");
return application.exec();
}
#include "main.moc"
Main.qml
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.1
ApplicationWindow {
id: window
width: 200
height: 250
visible: true
ColumnLayout {
anchors.fill: parent
anchors.margins: 10
ListView {
Layout.fillWidth: true
Layout.fillHeight: true
model: backend.createModel()
delegate: Text {
anchors.horizontalCenter: parent.horizontalCenter
text: model.display
}
}
Button {
Layout.alignment: Qt.AlignCenter
text: qsTr("Garbage Collect")
onClicked: gc()
}
}
}
Voici une capture d'écran du programme :
Dès que l'utilisateur clique sur le bouton, le ramasse-miettes s'exécute et détruit le ptr du modèle (la destruction est mise en évidence par la sortie "Création" et "Destruction" dans le stdout).
Je suis curieux de savoir pourquoi le pointeur a été détruit. J'ai remarqué qu'il ne mettait pas en place le paramètre ListView comme son parent, ce qui est tout à fait normal, je pensais que le moteur QML aurait utilisé une forme de pointeur de référence pour essayer de garder une trace de qui détient encore une référence à ce sujet. Existe-t-il un document qui donne un meilleur aperçu de la manière dont le ramassage des ordures et la propriété sont mis en œuvre ?
De même, existe-t-il une meilleure façon de structurer ce code tout en respectant les exigences de transmission d'un fichier QObject retour à QML.