test.qml
import QtQuick 2.0
import mylist 1.0
ListView {
width: 180; height: 200
model: PeopleListModel {
id: model1
}
delegate: Text {
text: name + ": " + number
}
MouseArea {
anchors.fill: parent
onClicked: model1.reload();
}
}
plugin.cpp
#include <QtQml/QQmlExtensionPlugin>
#include <QtQml/qqml.h>
#include <qdebug.h>
#include <qdatetime.h>
#include <qbasictimer.h>
#include <qcoreapplication.h>
#include <QAbstractItemModel>
#include <QStringList>
#include <iostream>
class People {
public:
People(QString const & name, QString const & number)
: name_(name), number_(number) {
}
QString name() const {
return name_;
}
QString number() const {
return number_;
}
private:
QString name_;
QString number_;
};
class PeopleListModel : public QAbstractListModel {
Q_OBJECT
public:
enum PeopleRoles {
NameRole = Qt::UserRole + 1,
NumberRole
};
PeopleListModel(QObject * parent = 0)
: QAbstractListModel(parent) {
/*
People p1("Dean", "186***");
addPeople(p1);
People p2("Crystal", "186***");
addPeople(p2);*/
}
void addPeople(People const & p) {
beginInsertRows(QModelIndex(), rowCount(), rowCount());
values_ << p;
endInsertRows();
}
int rowCount(QModelIndex const & parent = QModelIndex()) const {
return values_.count();
}
QVariant data(QModelIndex const & index, int role = Qt::DisplayRole) const {
std::cout << "data()" << std::endl;
std::cout << "index row: " << index.row() << " index column: " << index.column() << std::endl;
if (index.row() < 0 || index.row() >= values_.count()) {
std::cout << "s1" << std::endl;
return QVariant();
}
People const & p = values_[index.row()];
std::cout << "role: " << role << std::endl;
if (role == NameRole) {
return p.name();
}
else if (role == NumberRole) {
return p.number();
}
return QVariant();
}
Q_INVOKABLE void reload() {
std::cout << "--------------------" << std::endl;
std::cout << "reload()" << std::endl;
beginResetModel();
values_.clear();
endResetModel();
People p1("Dean", "176***");
addPeople(p1);
People p2("Crystal", "176***");
addPeople(p2);
std::cout << "values count: " << values_.count() << std::endl;
}
protected:
QHash<int, QByteArray> roleNames() const {
QHash<int, QByteArray> roles;
roles[NameRole] = "name";
roles[NumberRole] = "number";
return roles;
}
private:
QList<People> values_;
};
class QExampleQmlPlugin : public QQmlExtensionPlugin {
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtension.PeopleListModel")
public:
void registerTypes(char const * uri) {
qmlRegisterType<PeopleListModel>(uri, 1, 0, "PeopleListModel");
}
};
//********
当子类化QAbstractListModel
时,必须提供rowCount()
和data()
这2个函数的实现,当然也可以提供headerData()
函数的实现来使模型表现的更加良好.
如果在QML
中使用某模型,或者需要使用超出roleNames()
函数包含的默认角色时,必须重载它,也就是必须子类化QAbstractListModel
.
当需要链表模型可编辑时,你还必须提供setData()
函数的实现,以及提供flags
函数的实现以便它返回一个包含Qt::ItemIsEditable
的值.
需要注意的一点:QAbstractListModel
提供了columnCount()
函数的一个默认实现,它会通知视图,该模型中只有一列子项.
模型提供了调整链表数据结构的接口,这可以通过insertRows()
和removeRows()
函数来实现.,当实现这些函数时,最重要的是调用适当的函数,以便所有连接的视图都知道任何更改.
- 一个
insertRows()
函数的实现:必须先执行beginInsertRow()
函数,然后插入一行新的数据,再然后必须立即执行endInsertRows()
函数. - 一个
removeRows()
函数的实现:必须先执行beginRemoveRows()
函数,然后再移除一行数据,再然后必须立即执行endRemoveRows()
函数.
注意:子类化模型的一些通用准则可以参考Model Subclassing Reference
.