问题描述
我正在尝试使用 QQuickItem 制作一个列表视图组件并使用 QAbstractListModel 加载其模型。以下是我尝试过的步骤。
listviewComponent.qml
ListView {
required model
delegate: Text {
required property string type
required property string size
text: type + "," + size
}
}
Model.h
class Model
{
public:
Model(const QString& type,const QString& size);
QString type() const;
QString size() const;
private:
QString m_type;
QString m_size;
};
class CustomModel : public QAbstractListModel
{
Q_OBJECT
public:
enum Roles {
TypeRole = Qt::UserRole + 1,SizeRole
};
CustomModel(QObject* parent = 0);
void addElement(const Model& pElement);
int rowCount(const QModelIndex& parent = QModelIndex()) const;
QVariant data(const QModelIndex& index,int role = Qt::displayRole) const;
protected:
QHash<int,QByteArray> roleNames() const;
private:
QList<Model> m_list;
};
Model.cpp
Model::Model(const QString& type,const QString& size)
: m_type(type),m_size(size)
{
}
QString Model::type() const
{
return m_type;
}
QString Model::size() const
{
return m_size;
}
CustomModel::CustomModel(QObject* parent)
: QAbstractListModel(parent)
{
}
void CustomModel::addElement(const Model &pElement)
{
beginInsertRows(QModelIndex(),rowCount(),rowCount());
m_list << pElement;
endInsertRows();
}
int CustomModel::rowCount(const QModelIndex& parent) const {
Q_UNUSED(parent);
return m_list.count();
}
QVariant CustomModel::data(const QModelIndex& index,int role) const {
if (index.row() < 0 || index.row() >= m_list.count())
return QVariant();
const Model& mod = m_list[index.row()];
if (role == TypeRole)
return mod.type();
else if (role == SizeRole)
return mod.size();
return QVariant();
}
QHash<int,QByteArray> CustomModel::roleNames() const {
QHash<int,QByteArray> roles;
roles[TypeRole] = "type";
roles[SizeRole] = "size";
return roles;
}
Myclass.h
class myclass : public QObject
{
Q_OBJECT
public:
myclass();
inline int createUI(QQmlApplicationEngine &engine){
QQuickWindow *window = qobject_cast<QQuickWindow*>(engine.rootObjects().at(0));
if (!window) {
qFatal("Error: Your root item has to be a window.");
return -1;
}
QQuickItem *root = window->contentItem();
window->setWidth(600);
window->setHeight(500);
QQmlComponent listviewComp(&engine,QUrl(QStringLiteral("qrc:/listviewComponent.qml")));
CustomModel model;
model.addElement(Model("Wolf","Medium"));
model.addElement(Model("Polar bear","Large"));
model.addElement(Model("Quoll","Small"));
QQuickItem *listview = qobject_cast<QQuickItem*>(listviewComp.createWithInitialProperties({ {"model",QVariant::fromValue(&model)} }));
QQmlEngine::setobjectOwnership(listview,QQmlEngine::CppOwnership);
listview->setParentItem(root);
listview->setParent(&engine);
listview->setProperty("objectName","lv");
listview->setWidth(200);
listview->setHeight(100);
listview->setX(250);
listview->setY(30);
window->show();
return 0;
}
};
main.cpp
int main(int argc,char *argv[])
{
QGuiApplication app(argc,argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
engine.load(url);
QQmlContext *item = engine.rootContext();
myclass myClass;
item->setContextProperty("_myClass",&myClass);
myClass.createUI(engine);
return app.exec();
}
问题:Listview 正在显示但只有一行,但在 CustomModel 中添加了 3 行。我假设 createWithInitialProperties 存在一些问题,但无法破解它。
解决方法
这个问题是因为“model”是一个局部变量,一旦createUI执行完就会被销毁,你看到的第一行只是一个缓存,你实际上不应该看到一行(它看起来像一个错误)。解决办法是使用堆内存:
// ...
CustomModel *model = new CustomModel(window);
model->addElement(Model("Wolf","Medium"));
model->addElement(Model("Polar bear","Large"));
model->addElement(Model("Quoll","Small"));
QQuickItem *listview = qobject_cast<QQuickItem*>(listviewComp.createWithInitialProperties({ {"model",QVariant::fromValue(model)} }));
// ...