Qml Listview在重置模型

时间:2017-07-19 11:16:33

标签: c++ listview qt5

我有一个qml listview,它有一个来自c ++的模型。数据从另一个线程生成,并更新为c ++代码中的模型。之后,我使用BeginResetModel()更新qml中的listview。一切正常,除了qml中的视图开头,但我希望listview保持当前视图而不改变视图。

MWE:

listviewelement.cpp

ListViewElement::ListViewElement(int id,QString attr):m_id(id),m_attr(attr)
{

}

int ListViewElement::getId()
{
    return m_id;
}

QString ListViewElement::getAttr()
{
    return m_attr;
}

listviewmodel.cpp

ListViewModel::ListViewModel(QObject *parent): QAbstractListModel(parent)
  , m_items(new QList<ListViewElement*>()){

}


QHash<int,QByteArray> ListViewModel::roleNames() const
{
    qDebug() << Q_FUNC_INFO;
    QHash<int,QByteArray> roles;
    roles[ListViewEnum::ID] = "id";
    roles[ListViewEnum::ATTR] = "attr";
    return roles;
}

QVariant ListViewModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid() || index.row() > m_items->size()-1)
        return QVariant();

    ListViewElement *dobj = m_items->at(index.row());

    if (!dobj)
        return QVariant();

    switch (role) {
    case ListViewEnum::ID:
        return QVariant::fromValue(dobj->getId());
    case ListViewEnum::ATTR:
        return QVariant::fromValue(dobj->getAttr());
    default:
        return QVariant();
    }
}

int ListViewModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return m_items? m_items->size(): 0;
}

void ListViewModel::generateData()
{
    ListViewElement *ele = new ListViewElement(1,"attribute");
    m_items->append(ele);
    beginResetModel();
    endResetModel();
}

的main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "listviewmodel.h"
#include <QQmlContext>
#include <QTimer>

int main(int argc, char *argv[])
{
    ListViewModel model;
    QTimer *timer = new QTimer();
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("listViewModel",&model);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    QObject::connect(timer,SIGNAL(timeout()),&model,SLOT(generateData()));

    timer->start(1000);
    return app.exec();
}

main.qml

import QtQuick 2.5
import QtQuick.Window 2.2

Window {
    id: appMain
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    color: "#FFFF88"

    ListView {
        id: mainListView
        width: parent.width
        height: parent.height
        spacing: 10
        highlight: Rectangle {color: "green";radius: 5; focus: true}
        highlightFollowsCurrentItem: true
        focus: true
        cacheBuffer: 100
        model: listViewModel
        delegate: Rectangle {
            width: parent.width
            height: 35
            color: "transparent"
            Text {
                text: "\t" + id + "\t" + attr
            }

            MouseArea {
                width: parent.width
                height: parent.height
                onClicked: {
                    console.log("click item" + index)
                    mainListView.currentIndex = index
                }
            }
        }
    }

    Item {
        id: scrollBar
        width: 12; height: mainListView.height
        anchors.left: mainListView.left
        opacity: 0.7
        property real position: mainListView.visibleArea.yPosition
        property real pageSize: mainListView.visibleArea.heightRatio/2
        property int orientation: Qt.Vertical
        visible: true

        Rectangle {
            id: background
            anchors.fill: parent
            radius: scrollBar.orientation == Qt.Vertical ? (width/2 - 1) : (height/2 - 1)
            color: "white"
            opacity: 1.0
        }

        Rectangle {
            x: scrollBar.orientation == Qt.Vertical ? 1 : (scrollBar.position *(scrollBar.width - 2) + 1)
            y: scrollBar.orientation == Qt.Vertical ? (scrollBar.position *(scrollBar.height - 2) + 1) : 1
            width: scrollBar.orientation == Qt.Vertical ? (parent.width - 2) : (scrollBar.pageSize * (scrollBar.width - 2))
            height: scrollBar.orientation == Qt.Vertical ? (scrollBar.pageSize * (scrollBar.height - 2)) : (parent.height - 2)
            radius: scrollBar.orientation == Qt.Vertical ? (width/2 - 1) : (height/2 - 1)
            color: "black"
            opacity: 0.2
        }
    }
}

1 个答案:

答案 0 :(得分:0)

从我看到的,我有几个建议,虽然我没有测试,所以它可能会或可能不会。

  • 我看到你只附加了数据,那么为什么要在逐行插入行时重置模型并使用beginInsertRows() and endInsertRows()方法呢?
  • 如果这没有帮助,您可以将QML连接到模型的modelAboutToBeReset()信号(为此编写处理程序onModelAbouttoBeReset)并在重置之前保存当前索引,然后在重置之后模型,使用处理程序onModelReset通过调用ListView
  • 的'positionViewAtIndex(index,mode)'方法将listview放在此索引处

P.S。您必须在来电beginResetModel()endResetModel()

之间更改模型
相关问题