我已经构建了一个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从未按预期渲染对象 . 但也许这完全值得另一个问题 .