如何在ListModel中附加元素后更新QML ListView?

时间:2016-04-05 16:35:50

标签: c++ qt listview qml

我的QML中有ListView

ListView {
    id: listView1
    width: parent.width
    height: parent.height
    interactive: true
    clip: true
    visible: true

    property int elementH: 200

    Component.onCompleted: {
        mSingals.setPlotList(listView1);
    }

    function addImage(src) {
        listModel.append({"imageSrc": src});
    }

    function clear() {
        listModel.clear();
    }

    function redraw() {
        // ?????
        //listView1.update();
    }

    model: ListModel {
        id: listModel
        objectName: lModel
    }

    delegate: Rectangle {
        id: delegateItem
        width: listView1.width; height: listView1.elementH
        color: "blue"
        Image {
            anchors.left: parent.left
            source: imageSrc
            visible: true
        }
    }
}

首先,我使用图像提供程序和函数addImage(src)添加一些项目:

QVariant qv(QString("image://plots/").append(imageName));
QMetaObject::invokeMethod(plotList, "addImage", Q_ARG(QVariant, qv));

一切正常,ListView会自动更新。 然后我清除ListModel中的所有项目并添加一些新项目:

QMetaObject::invokeMethod(plotList, "clear");
QVariant qv(QString("image://plots/").append(someNewImage));
QMetaObject::invokeMethod(plotList, "addImage", Q_ARG(QVariant, qv));

ListView即使使用以下内容也不会更新:

QMetaObject::invokeMethod(plotList, "redraw");

所以我必须多次向上和向下滚动以使旧元素消失并出现新元素,但无论如何,无论我做什么,20的第一个元素都保持不变。

我应该在redraw()中使用什么来强制ListView更新? 也许会以某种方式发出dataChanged的{​​{1}}信号?

3 个答案:

答案 0 :(得分:1)

感谢您的回答!在我的情况下,问题是图像的名称。名称保持不变,虽然图像提供者可以通过此名称提供新图像,但ListView不会请求新图像。所以现在我只需更改每次更新的名称。

答案 1 :(得分:0)

好吧,你不需要做任何事情来获得正确的行为。我认为这个问题与C ++中的事情有关,这是以阻塞方式发生的,并没有给对象提供处理事件的时间。

尝试使用invokeMethod()的排队连接。

QMetaObject::invokeMethod(plotList, "addImage", Qt::QueuedConnection, Q_ARG(QVariant, qv));

然而,从C ++访问QML函数意味着“糟糕的设计”,你不应该这样做,QML应该访问C ++,反之亦然。如果你需要在C ++中组合实际的字符串那么多,你可以使用一个信号并用它发出字符串,并将它连接到QML处理程序,这样你就可以从QML与模型交互。

答案 2 :(得分:0)

这应该通过将QML Image的cache属性设置为false来解决。来自http://doc.qt.io/qt-5/qquickimageprovider.html的图片缓存部分:

  

QQuickImageProvider返回的图像会自动缓存,类似于QML引擎加载的任何图像。当从缓存加载带有“image://”前缀的图像时,不会为相关图像提供程序调用requestImage()和requestPixmap()。如果应始终从图像提供程序中提取图像,并且根本不应缓存该图像,请将相关图像的缓存属性设置为false