2016-11-04 66 views
1

我有一個通過QStandardItemModel獲取數據的QML TreeView。當應用程序正在運行時,我按下一個添加新條目的按鈕。我知道數據正在改變,但QML TreeView未更新。我也試過beginResetModel()endResetModel()。在加載應用程序時,數據在TreeView中正確顯示,但在修改模型中的數據時TreeView不會更改。在將新數據添加到模型後,QML TreeView在運行時不會更新

treeviewmodel.cpp

#include <QDebug> 
#include <QStandardItemModel> 
#include "treeviewmodel.h" 

TreeViewModel::TreeViewModel(QObject *parent) : 
    QStandardItemModel(parent) 
{ 
    m_roleNameMapping[TreeViewModel_Role_Name] = "name_role"; 

    QStandardItem* entry; 
    entry = new QStandardItem(QString("my_entry")); 
    entry->setData("abc", TreeViewModel_Role_Name); 

    auto childEntry = new QStandardItem("my_child_entry"); 
    childEntry->setData("def",TreeViewModel_Role_Name); 
    entry->appendRow(childEntry); 
    appendRow(entry); 

} 
TreeViewModel& TreeViewModel::Instance() 
{ 
    static TreeViewModel instance; //Guaranteed to be destroyed 
    return instance; 
} 
void TreeViewModel::addEntry() 
{ 
    qDebug() << "Adding entry..."; 

    QStandardItem* entry; 
    entry = new QStandardItem(QString("my_entry")); 
    entry->setData("Second Entry", TreeViewModel_Role_Name); 
    auto childEntry = new QStandardItem("my_child_entry"); 
    childEntry->setData("Second Entry Child",TreeViewModel_Role_Name); 
    entry->appendRow(childEntry); 
    appendRow(entry); 
    qDebug() << rowCount(); //Increases everytime I call the function 
          //Data is being added 
} 
QHash<int, QByteArray> TreeViewModel::roleNames() const 
{ 
    return m_roleNameMapping; 
} 

main.qml

import treeModel 1.0 
... 
MyTreeModel { 
    id: theModel 
} 

//Left Tree View 
Rectangle { 
    id: leftView 
    Layout.minimumWidth: 50 
    width: 200 
    //Layout.fillWidth: true 
    color: "white" 
    TreeView { 
     id: treeView 
     anchors.fill: parent 
     model: theModel 
     TableViewColumn { 
      role: "name_role" 
      title: "Name" 
     } 
     TableViewColumn { 
      role: "description_role" 
      title: "Description" 
     } 
    } 
} 

ToolButton { 
    iconSource: "lock.png" 
    onClicked: { 
    treeviewmodel.addEntry() 
    } 
} 

的main.cpp

QQmlContext* treeViewModelCtx = engine.rootContext(); 
treeViewModelCtx->setContextProperty("treeviewmodel", &TreeViewModel::Instance()); 

//Register types 
qmlRegisterType<TreeViewModel>("treeModel", 1, 0, "MyTreeModel"); 
+0

作爲臨時解決辦法,'treeviewmodel = treev在調用'addEntry'之後的'iewmodel'也許有效。 – skypjack

+0

我懷疑你必須在'addEntry'內發出['dataChanged'](http://doc.qt.io/qt-5/qabstractitemmodel.html#dataChanged)來通知視圖必須重新加載數據。它發揮這種信號的作用嗎? – skypjack

+0

對'QStandardItemModel :: appendRow' *的調用應導致發出'QAbstractItemModel :: rowsInserted'信號。嘗試將該信號連接到一個虛擬插槽以驗證它正在發射。 –

回答

1

我希望這個例子可以幫助。不幸的是,我沒有你的整個代碼來看看問題出在哪裏。

也許鑰匙是dataroleNames方法。

在本例中,我們還有一個名爲addButton的按鈕來添加新項目。

的main.cpp

#include "animalmodel.h" 

#include <QGuiApplication> 
#include <QQmlApplicationEngine> 
#include <qqmlcontext.h> 
#include <qqml.h> 

int main(int argc, char ** argv) 
{ 
    QGuiApplication app(argc, argv); 

    AnimalModel model; 
    model.addAnimal("Wolf", "Medium"); 
    model.addAnimal("Polar bear", "Large"); 
    model.addAnimal("Quoll", "Small"); 

    QQmlApplicationEngine engine; 

    QQmlContext *ctxt = engine.rootContext(); 
    ctxt->setContextProperty("myModel", &model); 

    engine.load(QUrl(QStringLiteral("qrc:/view.qml"))); 

    return app.exec(); 
} 

animalmodel.h

#ifndef ANIMALMODEL_H 
#define ANIMALMODEL_H 

#include <QStandardItemModel> 

class AnimalModel : public QStandardItemModel 
{ 
    Q_OBJECT 
public: 
    enum AnimalRoles { 
     TypeRole = Qt::UserRole + 1, 
     SizeRole 
    }; 

    AnimalModel(QObject *parent = 0); 

    Q_INVOKABLE void addAnimal(const QString &type, const QString &size); 

    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; 

protected: 
    QHash<int, QByteArray> roleNames() const; 
}; 

#endif // ANIMALMODEL_H 

animalmodel.cpp

#include "animalmodel.h" 

AnimalModel::AnimalModel(QObject *parent) 
    : QStandardItemModel(parent) 
{ 

} 

void AnimalModel::addAnimal(const QString &type, const QString &size) 
{ 
    QStandardItem* entry = new QStandardItem(); 
    entry->setData(type, TypeRole); 

    auto childEntry = new QStandardItem(); 
    childEntry->setData(size, SizeRole); 
    entry->appendRow(childEntry); 

    appendRow(entry); 
} 

QVariant AnimalModel::data(const QModelIndex & index, int role) const { 
    QStandardItem *myitem = itemFromIndex(index); 

    if (role == TypeRole) 
     return myitem->data(TypeRole); 
    else if (role == SizeRole) { 
     if (myitem->child(0) != 0) 
     { 
      return myitem->child(0)->data(SizeRole); 
     } 
    } 

    return QVariant(); 
} 

QHash<int, QByteArray> AnimalModel::roleNames() const { 
    QHash<int, QByteArray> roles; 
    roles[TypeRole] = "type"; 
    roles[SizeRole] = "size"; 
    return roles; 
} 
+0

我通過'qmlRegisterType (「treeModel」,1,0,「MyTreeModel」)註冊了qml類型;'這會加載視圖的初始狀態,但不會刷新。你的方法奏效,謝謝。但是,當試圖在「TreeView」上選擇項目時,有沒有反應,您是否遇到過這個問題? –

+0

這很奇怪,如果我點擊'TreeView'中的一行,該行就不會被選中。我認爲這是這個bug:https://bugreports.qt.io/browse/QTBUG-47243。順便說一下,您發佈的鏈接已損壞。謝謝您的幫助! –

+0

(固定評論)對不起!我沒有意識到main.cpp中的那一行代碼。是的,這是問題。幹得好:)關於TreeViews,我不記得他們有任何問題。 Qt [有](http://doc.qt.io/qt-5/qtquickcontrols-filesystembrowser-example.html)是TreeView的一個很好的例子。也許它可以幫助你看看在這個例子中你是否遇到同樣的問題。 – Tarod

相關問題