2017-07-19 23 views
0

私はC++のモデルを持つqml listviewを持っています。データは別のスレッドから生成され、C++コードでモデルに更新されます。その後、qmlのリストビューを更新するためにBeginResetModel()を使用しました。 qmlのビューを除くすべてが最初から始まりますが、リストビューはビューを変更せずに現在のビューを保持します。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 
     } 
    } 
} 

答えて

0

私が見ていることから、私はいくつかの提案をしていますが、私はそれをテストしなかったので、今働いているかもしれません。

  • データを追加するだけなので、行を1つずつ挿入してbeginInsertRows() and endInsertRows()メソッドを使用するとモデルがリセットされるのはなぜですか?
  • QMLでモデルのmodelAboutToBeReset()信号に接続して(その場合はハンドラを書きます(onModelAbouttoBeReset)、リセットする前に現在のインデックスを保存してからモデルをリセットした後、ハンドラを使用してonModelResetを配置しますこのindexのリストビューは、 'positionViewAtIndex(index、mode)'メソッドを呼び出すことによってListView

PS通話間でモデルを変更する必要がありますbeginResetModel()endResetModel()

+0

お返事ありがとうございます。この例では、1行しか挿入しませんが、リストを複数行追加してソートすることができるので、 'resetModel'が必要です。実際、私は新しい位置を特定しようとしましたが、 'positionViewAtIndex'を使用しようとしましたが、動作しません – GAVD

関連する問題