【发布时间】:2016-09-16 11:39:07
【问题描述】:
我的组件数量不定,所以我尝试为每个组件分配自己的model。在这个例子中,我只是创建了一个,但想法是一样的。
GC() 有点随机,所以在示例中,我在单击后强制 gc() 以清除问题。发生的情况是model 被破坏并变为空。之后点击方法就不能使用了。
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:
#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 只是注册类型:
#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 变为空。
例如
qml: clicked on Sally
~BoxModel()
qml: clicked on undefined
我的问题是为什么是这个,当我仍然有参考时?
在示例中,onClicked 可以更改为 label.text 而不是 model.name 来修复,但真正的问题是,一般来说,model 是由任何时间的对象,任何数据。例如,当框需要重绘时。数据随机消失,取决于 GC。
我尝试让 c++ 管理动态模型的生命周期。如果我知道什么时候确切地 QML 完成了它,这可能会起作用。
感谢您提供信息和想法。
在 Windows 8.1/qt5.6mingw 上运行
EDIT1:文件作为要点, https://gist.github.com/anonymous/86118b67ec804e6149423c14792f312d
【问题讨论】:
-
这看起来像一个真正的错误,感谢您提供一个好的、干净的测试用例。去掉工厂,直接在QML中创建实例,是否还有问题:
model: new BoxModel()? -
有趣。如果我将
model: maker.makeModel()更改为model: BoxModel {}它可以工作。当我有多个这样的盒子时,我将看看这是否能解决我的问题。谢谢。 -
是的,这种方式可以工作,前提是可以对底层代码模式进行一些更改。它要求
BoxModel能够在没有任何工厂“了解”它的情况下独立存在。我遇到的问题是我需要在内部跟踪这些。必须用单例完成,但它可以这样工作。但是,动态版本也可以正常工作。谢谢。 -
是什么阻止您在构造函数中将实例添加到全局列表中,并在析构函数中将其删除?你不需要工厂。