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

How to update QML ListView after appending an element into ListModel?

本文关键字:更新 QML ListView 元素 添加 ListModel      更新时间:2023-10-16

我的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?可能以某种方式发出ListModeldataChanged信号?

感谢您的回答!在我的案例中,问题出在图像的名称上。名称保持不变,尽管图像提供程序可以通过这些名称提供新图像,但ListView没有请求新图像。所以现在我只是为每次更新更改名称。

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

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

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

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

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

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