我构建了一个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
添加了一个带有调试消息的析构函数,以便我可以验证是否正在释放旧对象。但他们不是!因此,我不是在_dataList
调用之前手动浏览clear()
,而是仅管理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析构函数中看到了断点/调试消息(我之前没有看到过),但这导致了一个新问题。我会在rootContext->setContextProperty()
QListViewPrivate::releaseItem()
中遇到崩溃(我认为这就是它的名称),这让我相信它正在尝试释放{{1}中已经清除的对象}。但如果是这样的话,为什么_dataList.clear()
的析构函数被调用了呢?
我现在的解决方案是在DataObject
之前致电rootContext()->setContextProperty("myModel", QVariant{});
。像这样:
_dataList.clear
但这感觉就像是黑客。
管理这些动态对象的“更好”方法是什么(我实际上发现这是Qt中最模糊的方面之一)?我可以将它们附加到一个父对象上,该对象在每次调用void loadNewData()
{
QList<Object*> modelList;
rootContext()->setContextProperty("myModel", QVariant{});
_dataList.clear();
...
时都会被重置,但是为了这个目的而存在一个对象似乎也不正确。
另一个问题是,当我尝试直接使用loadNewData
对象时:
_dataList
在将它声明为元类型(因此rootContext()->setContextProperty("myModel", QVariant::fromValue(_dataList));
)后,我无法完成这项工作,QML从未按预期呈现对象。但也许这完全值得另一个问题。