我已经构建了一个C / QML应用程序,其中我在QML ListView中使用基于QList的模型 . 我已经从Qt的例子中调整了它(http://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html),所以我将使用他们的代码来解决我的问题 .
假设我已将其示例代码调整为以下内容:
class MyDataWidget : public QQuickWidget
{
public:
MyDataWidget(QObject* parent = nullptr)
: QQuickWidget(parent)
{
setSource(QUrl("qrc:/qml/myDataWidget.qml"));
}
void loadNewData()
{
_dataList.clear();
_dataList.append(new DataObject("Item 1", "red"));
_dataList.append(new DataObject("Item 2", "green"));
_dataList.append(new DataObject("Item 3", "blue"));
_dataList.append(new DataObject("Item 4", "yellow"));
rootContext()->setContextProperty("myModel", QVariant::fromValue(_dataList));
}
private:
QList<QObject*> _dataList;
}
我还为 DataObject
添加了一个带有调试消息的析构函数,以便我可以验证是否正在释放旧对象 . 但他们不是!因此,我不是在 clear()
调用之前手动浏览 _dataList
,而是只管理 std::shared_ptr<QObject*>
的列表,以便代码最终看起来像:
public:
void loadNewData()
{
QList<Object*> modelList;
_dataList.clear();
auto temp = std::make_shared<DataObject>("Item 1", "red");
_dataList.push_back(temp);
modelList.push_pack(temp.get());
...
rootContext()->setContextProperty("myModel", QVariant::fromValue(modelList));
}
private:
QList<std::shared_ptr<QObject>> _dataList;
现在这种工作 . 我确实在我的DataObject析构函数中看到了断点/调试消息(我之前没有看到过),但这会导致一个新问题 . 我会在 QListViewPrivate::releaseItem()
rootContext->setContextProperty()
中遇到崩溃(我认为这就是它的名称),这让我相信它正试图释放已经在 _dataList.clear()
中清除的对象 . 但如果是这样的话,为什么要调用 DataObject
的析构函数呢?
我现在的解决方案是在 _dataList.clear
之前调用 rootContext()->setContextProperty("myModel", QVariant{});
. 像这样:
void loadNewData()
{
QList<Object*> modelList;
rootContext()->setContextProperty("myModel", QVariant{});
_dataList.clear();
...
但这感觉就像一个黑客 .
什么是管理这些动态对象的方法(我实际上发现这是Qt中最模糊的一个方面)?我可以将它们附加到一个父对象上,该对象在每次调用 loadNewData
时都会被重置,但是为了这个目的而存在一个对象似乎也不正确 .
另一个问题是,当我尝试直接使用 _dataList
对象时:
rootContext()->setContextProperty("myModel", QVariant::fromValue(_dataList));
在将其声明为元类型(因此 Q_DECLARE_METATYPE
)后,我无法完成这项工作,QML从未按预期渲染对象 . 但也许这完全值得另一个问题 .