您的位置:首页 > 其它

QML 中的 ListView 中的隐藏秘技

2016-05-01 21:24 253 查看

QML 中的 ListView 中的隐藏秘技

应该是 ListView 中
delegate
的秘技。

ListView 代理中获取下标

ListView {
model: 10
delegate: Text {
text: "index"+index
}
}


使用
index
来获取代理在视图中展示的是哪个数据。(只此一条方法)

ListView 代理中获取到一条模型记录的某个字段

ListView {
width: 400
height: 400
model: ListModel {
ListElement {
age: 1
}
ListElement {
age: 2
}
ListElement {
age: 3
}
ListElement {
age: 4
}
}
delegate: Text {
text: age
}
}


如上所写,只要在
delegate
中写上对应的字段名(角色名)即可。

但是如果模型设置为 JavaScript 数组的时候,上诉写法就会报错了。如下:

ListView {
width: 400
height: 400
model: [
{ "age":1},
{ "age":2},
{ "age":3},
{ "age":4},
]
delegate: Text {
text: age            // ReferenceError: age is not defined
}
}


这个时候就需要获取一条模型记录,然后再取对应的字段(角色)了。

ListView 代理中获取一条模型记录

如何在代理中获取
model
的一条记录呢?

这里先说说
ListView::model
所能接受的数据类型吧。

int


QList<T>


QList<QObject*>


QListString


QAbstractItemModel


js array


ListModel


大概有七种类型,如果将
model
设置为数字的话,就会进行简单的类型转换,转成成
QList<int>
这种序列类型,并从小到大的进行数据填充。

视图通过代理将模型中数据一个一个进行绘制。那么代理中怎么获取到一条模型记录呢?

且看如下代码:

ListView {
anchors.fill: parent
model: [
{
"age": 1
},
{
"age": 2
},
{
"age": 3
},
{
"age": 4
}
]
delegate: Text {
property var item: modelData
property int age: item && item.age
text: age
}
}


ListView
在实例化代理中的图元时,会为每一个代理图元植入对应下标的
modelData
,这个就是一条模型记录,通过捕获
modelData
这个属性,然后在访问对应字段。

但是在
ListView
设置为
ListModel
的话,就无法使用
modelDate
这个属性了。然后直接给出兼容代码:

// 本方法不适合在 QAbstractItemModel* 及其子类中使用,除非 QAbstractItemModel* 及其子类有设定 modelData 这个角色
property var item: try {
// modelData 适用与 list<QtObject> 类型, js 数组类型,数字等
// 注意 QtObject* 除 QAbstractItemModel* 外都会转换成 list<QtObject> 这种类型

// console.debug(typeof modelData)
return modelData;
} catch(e) {
return ListView.view.model.get(index);
}


上诉代码不能和
QAbstractItemModel*
这个模型配套。

这时需要对
QAbstractItemModel*
的子类做一些功夫。首先设置
modelData
这个角色,然后在
QAbstractItemModel::data
这个函数中返回对应到
modelData
的记录,这个记录可以使用一个结构体存放,或者使用
QJasonObject
存放。

具体代码如下:

CppListModel


#ifndef CPPLISTMODEL_H
#define CPPLISTMODEL_H

#include <QAbstractListModel>

class CppListModel : public QAbstractListModel
{
Q_OBJECT
public:
explicit CppListModel(QObject *parent = 0);

enum Roles{
NameRole = Qt::UserRole + 1,            // name
AgeRole,                                // age
ModelDataRole,                          // modelData
};

QHash<int, QByteArray> roleNames() const;
int rowCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
};

#endif // CPPLISTMODEL_H


实现:

#include "cpplistmodel.h"
#include <QJsonObject>
#include <QtDebug>

CppListModel::CppListModel(QObject *parent):
QAbstractListModel(parent)
{  }

QHash<int, QByteArray> CppListModel::roleNames() const
{
QHash<int, QByteArray> roleNames;
roleNames.insert(NameRole, "name");
roleNames.insert(AgeRole, "age");
roleNames.insert(ModelDataRole, "modelData");
return roleNames;
}

int CppListModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
// 返回固定
return 5;
}

QVariant CppListModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() < 0)
return QVariant();

if (index.row() >= 5) {
qWarning() << "SatelliteModel: Index out of bound";
return QVariant();
}

switch (role)
{
case NameRole:
return QString("this name from cpp");
case AgeRole:
return 551;
case ModelDataRole:
return QJsonObject {
{ "name", "this name from cpp"},
{ "age", 551 }
};
default:
break;
}
return QVariant();
}


在 QML 中使用:

import QtQuick 2.5
import QtQuick.Controls 1.4
import TestModel 1.0

ApplicationWindow {
visible: true
width: 360
height: 640
title: qsTr("Hello World")

CppListModel {
id: cppListModel
// name, age
}

ListView {
anchors.fill: parent
model: cppListModel
delegate: itemDelegate
}

Component {
id: itemDelegate
Item {

// 本方法不适合在 QAbstractItemModel* 及其子类中使用,除非 QAbstractItemModel* 及其子类有设定 modelData 这个角色
property var item: try {
// modelData 适用与 list<QtObject> 类型, js 数组类型,数字等
// 注意 QtObject* 除 QAbstractItemModel* 外都会转换成 list<QtObject> 这种类型

console.debug("typeof modelData", typeof modelData)
return modelData;
} catch(e) {
return ListView.view.model.get(index);
}

property string name    : item && item.age
property string age     : item && item.age
Text {
anchors.centerIn: parent
text: name + age
}
}
}
}


Using C++ Models with Qt Quick Views
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: