Qt 如何为QAbstractListModel派生模型实现类似get的QML ListModel方法

Qt 如何为QAbstractListModel派生模型实现类似get的QML ListModel方法,qt,qml,qt-quick,qtquick2,qabstractitemmodel,Qt,Qml,Qt Quick,Qtquick2,Qabstractitemmodel,我想在QML中使用QAbstractListModel派生模型。将模型绑定到视图已经非常有效了 我想要实现的下一件事是访问特定项及其角色的能力,就像使用QML ListModel一样 grid.model.get(index).DisplayRole 但是我不知道如何在我的QAbstractListModel派生模型中实现这个get方法 有什么提示吗?我的方法是直接向QML公开对象的属性。下面是它的实现-如果你想使用列表模型中的角色的经典方法,你不必在C++方面做任何特殊的事情,那么你的模型就

我想在QML中使用QAbstractListModel派生模型。将模型绑定到视图已经非常有效了

我想要实现的下一件事是访问特定项及其角色的能力,就像使用QML ListModel一样

grid.model.get(index).DisplayRole
但是我不知道如何在我的QAbstractListModel派生模型中实现这个get方法


有什么提示吗?

我的方法是直接向QML公开对象的属性。下面是它的实现-

如果你想使用列表模型中的角色的经典方法,你不必在C++方面做任何特殊的事情,那么你的模型就好像总是一样,它应该实现数据方法:

QVariant QAbstractItemModel::data(const QModelIndex & index, int role = Qt::DisplayRole) const
要从QML访问不同的角色,可以在ListView代理中使用
模型
附加属性:

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类做了一个示例,它公开了一个
count
属性和
get
-函数,类似于默认的QML ListModel:

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;
};

您可以向QAbstractItemModel派生类添加一个Q_可调用函数,如下所示:

...

Q_INVOKABLE QVariantMap get(int row);

...

QVariantMap get(int row) {
    QHash<int,QByteArray> names = roleNames();
    QHashIterator<int, QByteArray> i(names);
    QVariantMap res;
    while (i.hasNext()) {
        i.next();
        QModelIndex idx = index(row, 0);
        QVariant data = idx.data(i.key());
        res[i.value()] = data;
        //cout << i.key() << ": " << i.value() << endl;
    }
    return res;
}
。。。
Q_可调用的QVariantMap get(int行);
...
QVariantMap获取(整数行){
QHash name=roleNames();
QHashIterator i(名称);
QVariantMap res;
while(i.hasNext()){
i、 next();
QModelIndex idx=索引(行,0);
QVariant data=idx.data(i.key());
res[i.value()]=数据;

//cout这花了我很长时间才找到,因为Stackoverflow上有很多不正确的解决方案

我已经在这里发布了回复:


这适用于所有模型,无论是从QAbstractItemModel派生的还是直接在QML中构建的,甚至允许访问树形模型。

实现这一点的另一种方法是直接使用
QAbstractItemModel
的内置函数,例如通过

grid.model.data(grid.model.index(index, 0), 0 /*== Qt::DisplayRole*/)

这在技术上是可行的,但要求用户知道角色的数字代码,而不是指定字符串。这里的主要问题是,充其量只有内置功能来确定
roleNames()
。要将名称字符串正确映射到相应的数值,需要实现一个反转函数并使用
Q\u INVOKABLE
公开它,或者处理
roleNames()产生的
QHash
在QML中手动执行。

我想访问JS函数中特定索引和特定角色处的项。例如,
myString=grid.model.get(3).DisplayRole
。我不知道你的答案如何帮助我实现这一点。如果你在代理内部,我的答案会更一般。从外部访问特定索引的情况非常罕见,但它的工作方式应该与你尝试的方式相同。
myString=grid.model.get(3)。display
(不是DisplayRole),如果这不起作用,您可以遍历模型数据的所有属性,以查看哪些属性可用,因为我想它们没有文档记录(没有示例应用程序我无法做到)。如何才能
myString=grid.model.get(3).display
just work?QAbstractListModel没有名为get的方法。因此我必须自己实现它。这就是问题。我必须如何实现此方法?我认为QML get函数将调用QAbstractListModel的虚拟“数据”方法(这是获取数据的默认方法)。我可能需要设置一个示例应用程序,自己测试它,明天再来这里。我在另一个项目中使用了QabStretcListModel,这很简单。+1000--感谢这一点。
model
确实需要记录!它仍然不是(!?)。我真的看不到对象的属性是如何公开的。我不需要在某处看到Q_属性宏吗?我公开了整个对象。然后JS可以查找使用Q_属性宏声明的特定属性。您可以将
QModelIndex idx=index(row,0);
移出循环以提高性能。
...

Q_INVOKABLE QVariantMap get(int row);

...

QVariantMap get(int row) {
    QHash<int,QByteArray> names = roleNames();
    QHashIterator<int, QByteArray> i(names);
    QVariantMap res;
    while (i.hasNext()) {
        i.next();
        QModelIndex idx = index(row, 0);
        QVariant data = idx.data(i.key());
        res[i.value()] = data;
        //cout << i.key() << ": " << i.value() << endl;
    }
    return res;
}
grid.model.data(grid.model.index(index, 0), 0 /*== Qt::DisplayRole*/)