2017-07-18 113 views
0

我正在嘗試使用QML TreeView模型。來自Qt的例子不包括如何創建模型。我讀了這個post並試圖使用@Tarod的代碼,但結果並不是我所期望的。爲QML TreeView創建模型

的main.cpp

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

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

    AnimalModel model; 
    model.addAnimal("wolf", "Medium"); 
    model.addAnimal("Bear", "Large"); 

    QQmlApplicationEngine engine; 
    QQmlContext *ctxt = engine.rootContext(); 
    ctxt->setContextProperty("myModel", &model); 
    engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); 
    if (engine.rootObjects().isEmpty()) 
     return -1; 

    return app.exec(); 
} 

animalmodel.h

#ifndef ANIMALMODEL_H 
#define ANIMALMODEL_H 

#include <QStandardItemModel> 


class AnimalModel : public QStandardItemModel 
{ 
    Q_OBJECT //The Q_OBJECT macro must appear in the private section of a class definition that declares its own signals and slots or that uses other services provided by Qt's meta-object system. 
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; 
} 

main.qml

import QtQuick 2.6 
import QtQuick.Window 2.2 
import QtQuick.Controls 1.4 


ApplicationWindow { 
    visible: true 
    width: 640 
    height: 480 
    title: qsTr("Hello World") 

    menuBar: MenuBar { 
     Menu { 
      title: qsTr("&File") 
      MenuItem { 
       text: qsTr("&Open") 
       onTriggered: messageDialog.show(qsTr("Open Action Triggered")); 
      } 
      MenuItem { 
       text: qsTr("&Exit") 
       onTriggered: Qt.quit(); 
      } 
     } 
    } 


    TreeView { 
     anchors.fill: parent 
     model: myModel 
     TableViewColumn { 
      title: "Name" 
      role: "type" 
      width: 300 
     } 
     TableViewColumn { 
      title: "Size" 
      role: "size" 
      width: 300 
     } 
    } 
} 

我得到的是這樣的: Result

我想要的是作爲動物類型的孩子的動物大小。

回答

2

模型子類是Qt中最差的雷區中的一個。建議始終是通過模型測試(https://wiki.qt.io/Model_Test)以查看是否所有內容都正確實施。

。另一方面,在90%的病例,你不需要子類的模型在所有的Qt提供默認的模型工作得非常好。我會做的僅僅是使用QStandardItemModel使用,在C++方面,只有化QAbstractItemModel接口(即強迫自己使用QAbstractItemModel* model = new QStandardItemModel(/*parent*/);)這樣一來,如果將來你覺得你真的需要重新實現模型(效率),你只需要在現有代碼中更改1行。

你的情況:

void AnimalModel::addAnimal(const QString &type, const QString &size) 
{ 
    if(columnCount()==0) insertColumn(0); // make sure there is at least 1 column 
    insertRow(rowCount()); // add a row to the root 
    const QModelIndex addedIdx = index(rowCount()-1,0); 
    setData(addedIdx, type, TypeRole); // set the root data 
    insertRow(rowCount(addedIdx),addedIdx); // add 1 row ... 
    insertColumn(0,addedIdx); // ... and 1 column to the added root row 
    setData(index(0,0,addedIdx), size, SizeRole); // set the data to the child 

}