Qt5.6 QML,为什么动态模型在垃圾回收后会被销毁? [英] Qt5.6 QML, why are dynamic models destroyed after garbage collection?

查看:22
本文介绍了Qt5.6 QML,为什么动态模型在垃圾回收后会被销毁?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有可变数量的组件,所以我试图给每个组件自己的model.在这个例子中,我只是创建了一个,但想法是一样的.

I have a variable number of components, so i'm trying to give each one its own model. In this example, i just create one, but the idea is the same.

GC() 有点随机,所以在示例中,我在单击后强制 gc() 以清除问题.发生的情况是 model 被破坏并变为空.之后点击方法就不能使用了.

GC() is a bit random, so in the example, i force the gc() after a click to flush out the problem. What happens is that the model is destroyed and becomes null. after that the click method cannot use it.

main.qml:

import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.2

import com.example.qml 1.0

ApplicationWindow
{
    visible: true
    width: 640
    height: 480

    // builder of dynamic models
    ModelFactory { id: maker }

    Column
    {
        anchors.fill: parent
        Repeater
        {
            // create dynamic model
            model: maker.makeModel();
            delegate: Label
            {
                id: label
                text: model.name

                MouseArea
                {
                    anchors.fill: parent
                    onClicked:
                    {
                        // works once until gc()
                        console.log("clicked on " + model.name)

                        // wont work anymore. model is destroyed
                        gc();
                    }
                }
            }

        }
    }
}

c++/mymodel.h:

c++/mymodel.h:

#include <QAbstractListModel>
#include <QQmlApplicationEngine>
#include <QObject>
#include <QString>
#include <QDebug>

class BoxModel : public QAbstractListModel
{
    Q_OBJECT

public:

    ~BoxModel()
    {
        // see that it does get destroyed
        qDebug() << "~BoxModel()";
    }

    int rowCount(const QModelIndex& parent = QModelIndex()) const override
    {
        return 5;
    }  

    QVariant data(const QModelIndex &index, int role) const override
    {
        int ix = index.row();
        if (ix < 1) return "Larry";
        if (ix < 2) return "Barry";
        if (ix < 3) return "Gary";
        if (ix < 4) return "Harry";
        return "Sally";
    }

    QHash<int, QByteArray> roleNames() const override
    {
        QHash<int, QByteArray> roles;
        roles[Qt::UserRole+1] = "name";
        return roles;
    }

};

class ModelFactory: public QObject
{
    Q_OBJECT

public:

    Q_INVOKABLE BoxModel* makeModel()
    {
        return new BoxModel();
    }    
};

main.cpp 只是注册类型:

main.cpp just registers the types:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <qqmlcontext.h>
#include <qqml.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
#include "mymodel.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;

    qmlRegisterType<BoxModel>("com.example.qml", 1, 0, "BoxModel");
    qmlRegisterType<ModelFactory>("com.example.qml", 1, 0, "ModelFactory");

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    return app.exec();
}

你看到了什么:

单击任何名称.它将工作一次,之后它们将是未定义的,因为 model 变为 null.

Click on any of the names. it will work once and after that they will be undefined because model becomes null.

例如

qml: clicked on Sally
~BoxModel()
qml: clicked on undefined

我的问题是为什么是这个,当我仍然有参考时?

My question is why is this, when i still have a reference to it?

在示例中,onClicked 可以改为 label.text 而不是 model.name 来修复,但是 real 问题在于,一般来说,model 可以随时被对象访问,获取任何数据.例如,当框需要重绘时.数据随机消失,取决于 GC.

In the example, onClicked could be changed to label.text rather than model.name to fix, but the real problem is that, in general, the model is accessed by the object at any time, for any data. For example, when the box needs to redraw. randomly the data is gone, depending on GC.

我尝试让 c++ 管理动态模型的生命周期.如果我知道什么时候确切地 QML 完成了它,这可能会起作用.

I've tried making c++ manage the life of the dynamic model. this could work if i know when exactly QML has finished with it.

感谢您提供信息和想法.

thanks for info and ideas.

在 Windows 8.1/qt5.6mingw 上运行

running on windows 8.1/qt5.6mingw

文件作为要点,https://gist.github.com/anonymous/86118b67ec804e6149423c14792f312d

推荐答案

我知道这是一个老问题,但我刚刚遇到了类似的问题,在写我的过程中发现了你的问题.请参阅 QObject 在放入 QML 变量后被销毁 全文,我会在这里引用.

I know this is an old question, but I've just faced similar issue, and found your question in process of writing mine. See QObject gets destroyed after being put into QML variable for full story, and I'll cite it here.

我发现如果我在将 QObject 传递给 QML 之前设置它的父对象,那么它不会被删除.因此,我得出的结论是,将无父级 QObject 传递到 QML 范围内会使该范围成为 QObject 的父级,并在范围结束后调用其析构函数.

What I've figured out that if I set the parent of that QObject before I pass it into QML, then it doesn't get deleted. So, I've concluded that passing unparented QObject into QML scope makes that scope become a parent of QObject and call its destructor after scope ends.

这篇关于Qt5.6 QML,为什么动态模型在垃圾回收后会被销毁?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆