Qt/QML 如何 return QList<T> 从 QAbstractListModel 的虚拟数据方法中收集
Qt/QML How to return QList<T> collection from virtual data metod from QAbstractListModel
我想总结一下要做什么。我有一个 DataObject
class 有成员:
QString first;QString last;QList<SubObject*> m_sublist;
我正在为此使用 QAbstractListModel
。我可以首先和最后引用 listview,但不能引用 m_sublist[0].lesson
。它给我这样的错误:
Cannot read property 'lesson' of undefined.
我的代码:
dataobject.h
class SubObject :public QObject
{
Q_OBJECT
public:
SubObject(const QString &lesson,QObject *parent = 0);
const QString lesson;
private:
// bool operator==(const SubObject* &other) const {
// return other->lesson == lesson;
// }
};
class DataObject :public QObject{
Q_OBJECT
public:
DataObject(const QString &firstName,
const QString &lastName,
const QList<SubObject*> &sublist);
QString first;
QString last;
QList<SubObject*> m_sublist;
};
simplelistmodel.h
class SimpleListModel : public QAbstractListModel {
Q_OBJECT
public:
SimpleListModel(QObject *parent=0);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QHash<int,QByteArray> roleNames() const { return m_roleNames; }
private:
// Q_DISABLE_COPY(SimpleListModel);
QList<DataObject*> m_items;
static const int FirstNameRole;
static const int LastNameRole;
static const int SubListRole;
QHash<int, QByteArray> m_roleNames;
};
simplelistmodel.cpp
const int SimpleListModel::FirstNameRole = Qt::UserRole + 1;
const int SimpleListModel::LastNameRole = Qt::UserRole + 2;
const int SimpleListModel::SubListRole = Qt::UserRole + 3;
SimpleListModel::SimpleListModel(QObject *parent) :
QAbstractListModel(parent) {
// Create dummy data for the list
QList<SubObject*> mysublist;
mysublist.append(new SubObject("MAT"));
mysublist.append(new SubObject("FEN"));
DataObject *first = new DataObject(QString("Arthur"), QString("Dent"),mysublist);
DataObject *second = new DataObject(QString("Ford"), QString("Prefect"),mysublist);
DataObject *third = new DataObject(QString("Zaphod"), QString("Beeblebrox"),mysublist);
m_items.append(first);
m_items.append(second);
m_items.append(third);
// m_roleNames = SimpleListModel::roleNames();
m_roleNames.insert(FirstNameRole, QByteArray("firstName"));
m_roleNames.insert(LastNameRole, QByteArray("lastName"));
m_roleNames.insert(SubListRole, QByteArray("subList"));
}
int SimpleListModel::rowCount(const QModelIndex &) const {
return m_items.size();
}
QVariant SimpleListModel::data(const QModelIndex &index,
int role) const {
if (!index.isValid())
return QVariant(); // Return Null variant if index is invalid
if (index.row() > (m_items.size()-1) )
return QVariant();
DataObject *dobj = m_items.at(index.row());
switch (role) {
case Qt::DisplayRole: // The default display role now displays the first name as well
case FirstNameRole:
return QVariant::fromValue(dobj->first);
case LastNameRole:
return QVariant::fromValue(dobj->last);
case SubListRole:
return QVariant::fromValue(dobj->m_sublist);
default:
return QVariant();
}
}
main.cpp
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
SimpleListModel model;
QQmlContext *classContext = engine.rootContext();
classContext->setContextProperty("absmodel",&model);
engine.load(QUrl(QStringLiteral("qrc:/myuiscript.qml")));
return app.exec(); }
myuiscript.qml
import QtQuick 2.0
import QtQuick.Window 2.0
Window {
id: bgRect
width: 200
height: 200
color: "black"
visible: true
ListView {
id: myListView
anchors.fill: parent
delegate: myDelegate
model: absmodel
}
Component {
id: myDelegate
Item {
width: 200
height: 40
Rectangle {
anchors.fill: parent
anchors.margins: 2
radius: 5
color: "lightsteelblue"
Row {
anchors.verticalCenter: parent.verticalCenter
Text {
text: firstName
color: "black"
font.bold: true
}
Text {
text: subList[0].lesson
color: "black"
}
}
}
}
}
}
我找不到任何解决方案。虚拟数据模型 returns 单一类型的对象。 FirsName
是一个字符串。我不能像 firstName(rolename)
这样引用 listview 委托。 LastName
也像 lastName(rolename)
一样引用。但我不能像 sublist[0].lesson
.
那样引用 subList(roleNames)
我的目标很简单。我想通过使用角色名将单一类型 (int,QString ....)
引用到委托中的文本。我无法使用 rolename(subList[0].lesson)
将集合 type(QList<SubObject*>)
引用到委托中的文本。如何实现它们?
让我们逐步修复它。 QML 中的这一行 text: subList[0].lesson
产生错误消息
TypeError: Cannot read property 'lesson' of undefined
这意味着 subList[0]
是一个未定义的对象,QML 引擎无法从该对象读取任何 属性,包括 lesson
。事实上,subList
return 从模型中编辑是一个明确定义的 QList<SubObject*>
对象,但不是 subList[0]
,因为 QList<SubObject*>
不是 QML 列表。要正确地pass a list from C++ to QML、return一个QVariantList
而不是QList
。
//class DataObject
DataObject(const QString &firstName,
const QString &lastName,
const QVariantList &sublist);
QVariantList m_sublist; //use QVariantList instead of QList<SubObject*>
//---
//SimpleListModel::SimpleListModel
QVariantList mysublist; //use QVariantList instead of QList<SubObject*>
mysublist.append(QVariant::fromValue(new SubObject("MAT", this))); //remember parent
mysublist.append(QVariant::fromValue(new SubObject("FEN", this)));
//...
现在,subList[0]
可以在 QML 中访问,但不能 subList[0].lesson
。要 access properties in a C++ class,用 Q_PROPERTY
宏显式定义 属性。
class SubObject :public QObject
{
Q_OBJECT
Q_PROPERTY(QString lesson READ getLesson NOTIFY lessonChanged)
public:
SubObject(const QString &lesson,QObject *parent = 0):
QObject(parent), m_lesson(lesson){;}
QString getLesson() const {return m_lesson;}
signals:
void lessonChanged();
private:
QString m_lesson;
};
QML 代码现在可以工作了。
我想总结一下要做什么。我有一个 DataObject
class 有成员:
QString first;QString last;QList<SubObject*> m_sublist;
我正在为此使用 QAbstractListModel
。我可以首先和最后引用 listview,但不能引用 m_sublist[0].lesson
。它给我这样的错误:
Cannot read property 'lesson' of undefined.
我的代码: dataobject.h
class SubObject :public QObject
{
Q_OBJECT
public:
SubObject(const QString &lesson,QObject *parent = 0);
const QString lesson;
private:
// bool operator==(const SubObject* &other) const {
// return other->lesson == lesson;
// }
};
class DataObject :public QObject{
Q_OBJECT
public:
DataObject(const QString &firstName,
const QString &lastName,
const QList<SubObject*> &sublist);
QString first;
QString last;
QList<SubObject*> m_sublist;
};
simplelistmodel.h
class SimpleListModel : public QAbstractListModel {
Q_OBJECT
public:
SimpleListModel(QObject *parent=0);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QHash<int,QByteArray> roleNames() const { return m_roleNames; }
private:
// Q_DISABLE_COPY(SimpleListModel);
QList<DataObject*> m_items;
static const int FirstNameRole;
static const int LastNameRole;
static const int SubListRole;
QHash<int, QByteArray> m_roleNames;
};
simplelistmodel.cpp
const int SimpleListModel::FirstNameRole = Qt::UserRole + 1;
const int SimpleListModel::LastNameRole = Qt::UserRole + 2;
const int SimpleListModel::SubListRole = Qt::UserRole + 3;
SimpleListModel::SimpleListModel(QObject *parent) :
QAbstractListModel(parent) {
// Create dummy data for the list
QList<SubObject*> mysublist;
mysublist.append(new SubObject("MAT"));
mysublist.append(new SubObject("FEN"));
DataObject *first = new DataObject(QString("Arthur"), QString("Dent"),mysublist);
DataObject *second = new DataObject(QString("Ford"), QString("Prefect"),mysublist);
DataObject *third = new DataObject(QString("Zaphod"), QString("Beeblebrox"),mysublist);
m_items.append(first);
m_items.append(second);
m_items.append(third);
// m_roleNames = SimpleListModel::roleNames();
m_roleNames.insert(FirstNameRole, QByteArray("firstName"));
m_roleNames.insert(LastNameRole, QByteArray("lastName"));
m_roleNames.insert(SubListRole, QByteArray("subList"));
}
int SimpleListModel::rowCount(const QModelIndex &) const {
return m_items.size();
}
QVariant SimpleListModel::data(const QModelIndex &index,
int role) const {
if (!index.isValid())
return QVariant(); // Return Null variant if index is invalid
if (index.row() > (m_items.size()-1) )
return QVariant();
DataObject *dobj = m_items.at(index.row());
switch (role) {
case Qt::DisplayRole: // The default display role now displays the first name as well
case FirstNameRole:
return QVariant::fromValue(dobj->first);
case LastNameRole:
return QVariant::fromValue(dobj->last);
case SubListRole:
return QVariant::fromValue(dobj->m_sublist);
default:
return QVariant();
}
}
main.cpp
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
SimpleListModel model;
QQmlContext *classContext = engine.rootContext();
classContext->setContextProperty("absmodel",&model);
engine.load(QUrl(QStringLiteral("qrc:/myuiscript.qml")));
return app.exec(); }
myuiscript.qml
import QtQuick 2.0
import QtQuick.Window 2.0
Window {
id: bgRect
width: 200
height: 200
color: "black"
visible: true
ListView {
id: myListView
anchors.fill: parent
delegate: myDelegate
model: absmodel
}
Component {
id: myDelegate
Item {
width: 200
height: 40
Rectangle {
anchors.fill: parent
anchors.margins: 2
radius: 5
color: "lightsteelblue"
Row {
anchors.verticalCenter: parent.verticalCenter
Text {
text: firstName
color: "black"
font.bold: true
}
Text {
text: subList[0].lesson
color: "black"
}
}
}
}
}
}
我找不到任何解决方案。虚拟数据模型 returns 单一类型的对象。 FirsName
是一个字符串。我不能像 firstName(rolename)
这样引用 listview 委托。 LastName
也像 lastName(rolename)
一样引用。但我不能像 sublist[0].lesson
.
subList(roleNames)
我的目标很简单。我想通过使用角色名将单一类型 (int,QString ....)
引用到委托中的文本。我无法使用 rolename(subList[0].lesson)
将集合 type(QList<SubObject*>)
引用到委托中的文本。如何实现它们?
让我们逐步修复它。 QML 中的这一行 text: subList[0].lesson
产生错误消息
TypeError: Cannot read property 'lesson' of undefined
这意味着 subList[0]
是一个未定义的对象,QML 引擎无法从该对象读取任何 属性,包括 lesson
。事实上,subList
return 从模型中编辑是一个明确定义的 QList<SubObject*>
对象,但不是 subList[0]
,因为 QList<SubObject*>
不是 QML 列表。要正确地pass a list from C++ to QML、return一个QVariantList
而不是QList
。
//class DataObject
DataObject(const QString &firstName,
const QString &lastName,
const QVariantList &sublist);
QVariantList m_sublist; //use QVariantList instead of QList<SubObject*>
//---
//SimpleListModel::SimpleListModel
QVariantList mysublist; //use QVariantList instead of QList<SubObject*>
mysublist.append(QVariant::fromValue(new SubObject("MAT", this))); //remember parent
mysublist.append(QVariant::fromValue(new SubObject("FEN", this)));
//...
现在,subList[0]
可以在 QML 中访问,但不能 subList[0].lesson
。要 access properties in a C++ class,用 Q_PROPERTY
宏显式定义 属性。
class SubObject :public QObject
{
Q_OBJECT
Q_PROPERTY(QString lesson READ getLesson NOTIFY lessonChanged)
public:
SubObject(const QString &lesson,QObject *parent = 0):
QObject(parent), m_lesson(lesson){;}
QString getLesson() const {return m_lesson;}
signals:
void lessonChanged();
private:
QString m_lesson;
};
QML 代码现在可以工作了。