QAbstractItemModel动态项插入

问题描述:

我为我的模型继承了QAbstractItemModel类。为了方便地插入新项目的模式,我写了一个方法:QAbstractItemModel动态项插入

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}); 
} 

这与而QListView运作良好,但QML的TreeView控件不更新值后一次显示了它:

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的类:

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

首先,如果没有封闭的'fooAboutToBeChanged',你不应该发出'fooChanged'。但即使如此,你仍然不应该发布布局改变。您已通过'beginInsertRows'和'endInsertRows'发出'rowsAboutToBeInserted'和'rowsInserted'信号,通知客户有关更改。 –

+0

只使用开始(结束)InsertRows没有结果。也许有idx对象的问题?我应该使用行索引作为父 - 行()或0或其他? –

+0

我并不是说'layoutChanged'发射是唯一的问题,但这绝对是一个问题,你不应该这样做:) –

例如,QML的ListView不适合显示树状结构,如目录树。它只适用于通常从QAbstractListModel继承的列表模型。如果您从QAbstractItemModel派生模型,则必须将其专门化,以使其行为与列表类似。

由于Qt 5.5在模块QtQuick.Controls(v1.4)中有一个QML TreeView组件。你可能想试试这个。

+0

问题中有错误。当然,我使用QTreeView和QML的TreeView。 –