2016-04-27 140 views
1

我爲我的模型繼承了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'發射是唯一的問題,但這絕對是一個問題,你不應該這樣做:) –

回答

0

例如,QML的ListView不適合顯示樹狀結構,如目錄樹。它只適用於通常從QAbstractListModel繼承的列表模型。如果您從QAbstractItemModel派生模型,則必須將其專門化,以使其行爲與列表類似。

由於Qt 5.5在模塊QtQuick.Controls(v1.4)中有一個QML TreeView組件。你可能想試試這個。

+0

問題中有錯誤。當然,我使用QTreeView和QML的TreeView。 –