QML中动态加载C++数据, 数据的生产使用C++代码,而显示则交给QML去做。
首先继承一个QAbstractListModel类
class WeekModel : public QAbstractListModel { }
这是一个关于获取系统时间,然后把时间传给QML层的类。
#include <QAbstractListModel>
#include <QString>
#include <QVariant>
/*为星期提供数据*/
class WeekModel : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(QString date READ date WRITE setDate NOTIFY dateChanged);
Q_PROPERTY(QString weekday READ weekday WRITE setWeekday NOTIFY weekdayChanged)
public:
WeekModel(QObject *parent = 0);
~WeekModel();
int rowCount(const QModelIndex & parent) const; //获取数组长度
QVariant data(const QModelIndex & index, int role) const; //如何获取每个数据
signals:
void dateChanged();
void weekdayChanged();
private:
QString m_date; // 日期
QString m_weekday; // 星期几
};
Q_PROPERTY 一般只对单一的一个变量。
其中 READ WRITE 方法C++实现, QML使用。NOTIFY 方法一般是C++发送,QML端做响应动作。
那么如果如何表示dates(比如10月1号,10月2号,10月3号。。。。),很自然的想到数组,或者List等所以model类要继承一个QAbstractListModel ,
实现2个方法:
int rowCount(const QModelIndex & parent) const; //获取数组长度
QVariant data(const QModelIndex & index, int role) const; //如何获取每个数据
在参数中(QModelIndex &index)int row = index.row(), 表示第几个元素, 系统会根据rowCount返回的长度,进行循环一遍, 至此所有的数据被取出来显示在qml中。
例:
int rowCount(const QModelIndex &parent = QModelIndex()) { return 7;} // 表示一周的时间(7天)
QVariant data(const QModelIndex &index, int role = Qt:DisplayRole)
{
//获取当天的时间
QDateTime current_date_time = QDateTime::currentDateTime();
// 根据index 推算要显示的时间
int addDay = index.row(); /* row is 0~6 here*/
current_date_time.addDays(addDay);
return current_date_time.toString("yyyy-mm-dd");
}
我们的工作至此完成一半了。
mian函数里注入
QQmlApplicationEngine engine;
QQmlContext *ctx = engine.rootContext();
ctx->setContextProperty("uiSender", uiSender);
QAbstractItemModel
可使用QAbstractItemModel的子类定义模型.如果有一个复杂的模型无法用其他方式实现,就可以使用这种方式.QAbstractItemModel在发生变化时会自动通知QML视图.
QAbstractItemModel子类向QML暴露的角色可使用QAbstractItemModel::setRoleNames()设置.默认的角色名称由Qt设置:
Qt Role QML角色名称
Qt::DisplayRole 显示
Qt::DecorationRole 修饰
下面的应用程序有一个QAbstractItemModel子类模型叫做AnialModel,具有type和size角色.为在QML中访问这些属性调用了QAbstractItemModel::setRoleNames():
class Animal
{
public:
Animal(const QString &type, const QString &size);
...
};
class AnimalModel : public QAbstractListModel
{
Q_OBJECT
public:
enum AnimalRoles {
TypeRole = Qt::UserRole + 1,
SizeRole
};
AnimalModel(QObject *parent = 0);
...
};
AnimalModel::AnimalModel(QObject *parent)
: QAbstractListModel(parent)
{
QHash<int, QByteArray> roles;
roles[TypeRole] = "type"; //添加自己定义的角色或者叫做属性, 供QML使用
roles[SizeRole] = "size";
setRoleNames(roles);
}
int main(int argc, char ** argv)
{
QApplication app(argc, argv);
AnimalModel model;
model.addAnimal(Animal("Wolf", "Medium"));
model.addAnimal(Animal("Polar bear", "Large"));
model.addAnimal(Animal("Quoll", "Small"));
QDeclarativeView view;
QDeclarativeContext *ctxt = view.rootContext();
ctxt->setContextProperty("myModel", &model);
...
这个模型显示在ListView中,代理可访问type和size角色:
ListView {
width: 200; height: 250
anchors.fill: parent
model: myModel
delegate: Text { text: "Animal: " + type + ", " + size } //这边直接使用type 和 size变量了。
}