我想在QML中使用QAbstractListModel派生模型。將模型綁定到視圖已經很好。如何實現QML ListModel類似QAbstractListModel派生模型的get方法
我想實現的下一件事就是訪問特定的項目和他們的角色一樣,可以用QML ListModel的
grid.model.get(index).DisplayRole
的能力,但我不知道如何實現這個get方法在我QAbstractListModel派生模型。
任何提示?
我想在QML中使用QAbstractListModel派生模型。將模型綁定到視圖已經很好。如何實現QML ListModel類似QAbstractListModel派生模型的get方法
我想實現的下一件事就是訪問特定的項目和他們的角色一樣,可以用QML ListModel的
grid.model.get(index).DisplayRole
的能力,但我不知道如何實現這個get方法在我QAbstractListModel派生模型。
任何提示?
您可以添加Q_INVOKABLE功能的化QAbstractItemModel派生類這樣的:用我的自定義模型
爲了完整這裏一個例子的ListView
...
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;
}
這將返回類似{ "bookTitle" : QVariant("Bible"), "year" : QVariant(-2000) }
所以你可以使用.bookTitle
我的方法是直接向QML公開對象的屬性。這裏是它的實現 - https://stackoverflow.com/a/14424517/1059494
我真的不知道對象的屬性是如何暴露的。我不需要在某處看到Q_PROPERTIES宏嗎? – avb
我公開整個對象。然後JS可以查找使用Q_PROPERTY宏聲明的特定屬性。 –
如果你想在列表模型中使用經典的角色方法,你不必在C++端做任何特殊的事情,你的模型就像總是一樣,它應該實現數據方法:
QVariant QAbstractItemModel::data(const QModelIndex & index, int role = Qt::DisplayRole) const
訪問從QML不同角色model
附加屬性可以在你的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的DOC文件(還) ,但要找到你可以訪問哪些屬性QML只需在調試模式下啓動應用程序,並在代理中放置一個斷點或將所有屬性打印到控制檯。順便說一下,委託內部的model
屬性是QQmlDMAbstractItemModelData類型,所以在後臺發生一些「Qt魔術」,看起來像列表模型數據的一些包裝,在Qt文檔中我仍然找不到任何官方的我自己用QML調試器和其他東西)。
如果您需要從代表外部訪問模型數據,我不認爲有任何內置功能,所以您必須自己做。
我爲它公開了一個count
財產和get
- 函數類似於默認QML ListModel的自定義QAbstractListModel類的例子:
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 {
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
}
}
我想訪問JS功能中特定索引和特定角色的項目。例如'myString = grid.model.get(3).DisplayRole'。我看不出你的答案如何幫助我實現這一目標。 – avb
如果你在委託人的內部,我的答案更一般。從外部訪問特定索引是非常罕見的,但它應該以與嘗試'myString = grid.model.get(3).display'(不是DisplayRole)相同的方式工作,如果這樣做不起作用,則可以迭代模型數據的所有屬性,以查看哪些屬性可用,因爲它們沒有記錄我想(我不能這樣做,沒有示例應用程序)。 – Xander
如何才能'myString = grid.model.get(3).display'工作? QAbstractListModel沒有稱爲get的方法。所以我必須自己來實現它。這就是問題所在。我該如何執行這個方法? – avb
這花了我很長時間才發現,因爲Stac上有很多不正確的解決方案koverflow。
我已回覆這裏:
How to access ListView's current item from qml
這適用於所有車型,無論是從化QAbstractItemModel衍生或直接在QML構建,甚至允許訪問樹形模型。
這樣做的另一種方法是直接使用QAbstractItemModel
的內置函數,例如,通過
grid.model.data(grid.model.index(index, 0), 0 /*== Qt::DisplayRole*/)
這在技術上有效,但要求用戶知道角色的數字代碼,而不是指定的字符串。這裏的主要問題是,至多隻有內置功能來確定roleNames()
。爲了將名稱字符串正確映射到相應的數字值,需要實現反轉功能並使用Q_INVOKABLE
對其進行曝光,或者手動處理由QML中的roleNames()
產生的QHash
。
您可以將'QModelIndex idx = index(row,0);'移出循環以提高性能。 –