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;
};
答
例如,QML的ListView不适合显示树状结构,如目录树。它只适用于通常从QAbstractListModel继承的列表模型。如果您从QAbstractItemModel派生模型,则必须将其专门化,以使其行为与列表类似。
由于Qt 5.5在模块QtQuick.Controls(v1.4)中有一个QML TreeView组件。你可能想试试这个。
+0
问题中有错误。当然,我使用QTreeView和QML的TreeView。 –
首先,如果没有封闭的'fooAboutToBeChanged',你不应该发出'fooChanged'。但即使如此,你仍然不应该发布布局改变。您已通过'beginInsertRows'和'endInsertRows'发出'rowsAboutToBeInserted'和'rowsInserted'信号,通知客户有关更改。 –
只使用开始(结束)InsertRows没有结果。也许有idx对象的问题?我应该使用行索引作为父 - 行()或0或其他? –
我并不是说'layoutChanged'发射是唯一的问题,但这绝对是一个问题,你不应该这样做:) –