2016-04-27 19 views
1

Ich geerbte QAbstractItemModel-Klasse für mein Modell. Um auf einfache Weise neue Elemente an das Modell einfügen I nächsten Methode geschrieben:QAbstractItemModel dynamische Elementeinfügung

void addItem(MyData *parent, MyData *children) { 
    QModelIndex idx = createIndex(parent->row(), 0, parent); 
    if (!idx.isValid()) { 
     return; 
    } 

    int childCount = parent->getChildCount(); 
    beginInsertRows(idx, childCount, childCount); 
    parent->addChild(children); 
    endInsertRows(); 

    emit layoutChanged(QList<QPersistentModelIndex>{idx}); 
} 

Es funktioniert gut mit QListView, aber QML des TreeView keine Aktualisierungen Werte, nachdem sie einmal zeigte es:

int main(int argc, char ** argv) { 
    Q_INIT_RESOURCE(ui); 
    QApplication application(argc, argv); 

    MyModel model; 

    for (int i = 0; i < 10; ++ i) { 
     MyData *firstLevelItem = new MyData(i); 

     for (int k = 0; k < 3; ++ k) { 
      MyData *secondLevelItem = new MyData(i); 
      model.addItem(firstLevelItem, secondLevelItem); 
     } 

     model.addItem(model.getRootItem(), firstLevelItem); 
    } 

    QQuickView view; 
    QQmlContext *context = view.rootContext(); 
    context->setContextProperty("MyModel", &model); 

    view.setSource(QUrl("qrc:///ui/form.qml")); 
    view.show(); 

    QTreeView t; 
    t.setModel(&model); 
    t.show(); 

    MyData *data = new MyData(2281488); 
    model.addItem(model.getRootItem(), data); 
    // t displays changes, view - not 

    return application.exec(); 
} 

MyData Klasse:

class MyModel; 

class MyData: public QObject { 
    Q_OBJECT 

public: 
    explicit MyData() : 
     QObject() { 
     _parent = nullptr; 
    } 

    ~MyData() { 
     qDeleteAll(_data); 
    } 

    // getters/setters 

    MyData *getChildItem(int index) const { 
     if (index < 0 || index >= _data.size()) { 
      return nullptr; 
     } 

     return _data[index]; 
    } 

    int getChildCount() const { 
     return _data.size(); 
    } 

    MyData *parent() const { 
     return _parent; 
    } 

    int row() const { 
     if (_parent) { 
      return _parent->_data.indexOf(const_cast<MyData *>(this)); 
     } else { 
      return 0; 
     } 
    } 

private: 
    void addChild(MyData *data) { 
     if (data) { 
      if (data->_parent) { 
       _parent->removeChild(data); 
      } 
      data->_parent = this; 
      _data << data; 
     } 
    } 

    void removeChild(MyData *data) { 
     _data.removeAll(data); 
    } 

    // some private fields 

    MyData *_parent; 

    QVector<MyData *> _data; 

    friend class MyModel; 
}; 
+0

Zuallererst sollten Sie "fooChanged" nicht ohne einschließendes 'fooAboutToBeChanged' ausgeben. Aber selbst dann sollten Sie keinen Layoutwechsel vornehmen. Sie informieren die Clients bereits über die Änderung, indem Sie die Signale "rowsAboutToBeInserted" und "rowsInserted" über "beginInsertRows" und "endInsertRows" ausgeben. –

+0

Mit nur begin (end) InsertRows haben kein Ergebnis. Vielleicht gibt es ein Problem mit dem IDX-Objekt? Sollte ich Zeilenindex als Eltern-> Zeile() oder 0 oder irgendetwas anderes verwenden? –

+0

Ich behaupte nicht, dass die 'layoutChanged' Emission das einzige Problem ist, aber es ist definitiv ein Problem, und Sie sollten es nicht tun :) –

Antwort

0

QMLs ListView eignet sich nicht zum Anzeigen baumähnlicher Strukturen, wie z. B. eines Verzeichnisbaums. Es funktioniert nur mit Listenmodellen, die normalerweise von QAbstractListModel geerbt werden. Wenn Sie Ihr Modell von QAbstractItemModel ableiten, müssen Sie es so spezialisieren, dass es sich wie eine Liste verhält.

Seit Qt 5.5 gibt es eine QML TreeView Komponente im Modul QtQuick.Controls (v1.4). Vielleicht möchten Sie dies versuchen.

+0

Es ist ein Fehler in der Frage. Natürlich benutze ich QTreeView und QML's TreeView. –