如果您想在列表模型中使用经典方法来处理角色,您不必在 c++ 端做任何特殊的事情,您的模型就像往常一样,它应该实现数据方法:
QVariant QAbstractItemModel::data(const QModelIndex & index, int role = Qt::DisplayRole) const
要从 QML 访问不同的角色,可以在 ListView 委托中使用 model 附加属性:
model.display // model.data(index, Qt::DisplayRole) in c++
model.decoration // Qt::DecorationRole
model.edit // Qt::EditRole
model.toolTip // Qt::ToolTipRole
// ... same for the other roles
我认为 Qt 文档中还没有记录,但要找出可以从 QML 访问的属性,只需在调试模式下启动应用程序并在委托中放置断点或打印所有属性到控制台。顺便说一句,委托中的model 属性是 QQmlDMAbstractItemModelData 类型,所以在后台发生了一些“Qt 魔法”,看起来像是列表模型数据的一些包装,但我仍然在 Qt 文档中找不到任何官方的关于它的信息(我自己用 QML 调试器和其他东西解决了这个问题)。
如果您需要从委托外部访问模型数据,我认为没有任何内置功能,因此您必须自己做。
我为自定义 QAbstractListModel 类做了一个示例,它公开了类似于默认 QML ListModel 的 count 属性和 get-function:
mylistmodel.h
class MyListModel : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
public:
explicit MyListModel(QObject *parent = 0);
int rowCount(const QModelIndex & = QModelIndex()) const override { return m_data.count(); }
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
Q_INVOKABLE int get(int index) const { return m_data.at(index); }
signals:
void countChanged(int c);
private:
QList<int> m_data;
};
mylistmodel.cpp
MyListModel::MyListModel(QObject *parent) :
QAbstractListModel(parent)
{
m_data << 1 << 2 << 3 << 4 << 5; // test data
emit countChanged(rowCount());
}
QVariant MyListModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() < 0 || index.row() >= rowCount())
return QVariant();
int val = m_data.at(index.row());
switch (role) {
case Qt::DisplayRole:
return QString("data = %1").arg(val);
break;
case Qt::DecorationRole:
return QColor(val & 0x1 ? Qt::red : Qt::green);
break;
case Qt::EditRole:
return QString::number(val);
break;
default:
return QVariant();
}
}
由于向 QML 公开属性和函数非常容易,我想这是一个很好的方法来了解它。
为了完整起见,这里有一个使用我的自定义模型的示例 ListView:
ListView {
anchors.fill: parent
model: MyListModel { id: myModel }
delegate: Text {
text: model.display
}
Component.onCompleted: {
console.log(myModel.count) // 5
console.log(myModel.get(0)) // 1
}
}