我正在尝试使用C ++在我的.qml文件(当我单击按钮时)中使用XML dataModel进行动态更改。为此,我正在返回一个Qt属性(GroupDataModel)。但是在返回对象之后,ListView不会改变,尽管我看到了model属性再次返回。
OBS:如果我从.qml中的XMLDataModel加载它,而不是加载C ++代码,它就可以工作。
这是我的XmlTest.hpp:
#ifndef XmlTest_HPP_
#define XmlTest_HPP_
#include <QObject>
#include <bb/cascades/GroupDataModel>
namespace bb { namespace cascades { class Application; }}
class XmlTest : public QObject
{
Q_OBJECT
Q_PROPERTY(bb::cascades::GroupDataModel* model READ model NOTIFY onModelChanged);
public:
XmlTest(bb::cascades::Application *app);
virtual ~XmlTest() {}
Q_INVOKABLE
bb::cascades::GroupDataModel *model();
Q_INVOKABLE
void setGroupDataModel();
signals:
void onModelChanged();
private:
bb::cascades::GroupDataModel *m_model;
};
#endif /* XmlTest_HPP_ */
和XmlTest.cpp:
#include "XmlTest.hpp"
#include <bb/cascades/Application>
#include <bb/cascades/QmlDocument>
#include <bb/cascades/AbstractPane>
#include <bb/data/XmlDataAccess>
using namespace bb::cascades;
using namespace bb::data;
XmlTest::XmlTest(Application *app)
: QObject(app)
{
m_model = new GroupDataModel();
qRegisterMetaType<GroupDataModel *>("GroupDataModel *");
QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this);
qml->setContextProperty("_xmlTest", this);
AbstractPane *root = qml->createRootObject<AbstractPane>();
app->setScene(root);
}
GroupDataModel *XmlTest::model()
{
qDebug("Returning m_model");
return m_model;
}
void XmlTest::setGroupDataModel()
{
XmlDataAccess xml;
QVariant xmlData = xml.load(QDir::currentPath() + "/app/native/assets/models/model.xml");
m_model->clear();
m_model->insertList(xmlData.toList());
qDebug("File loaded");
emit this->onModelChanged();
}
我的main.qml文件(只是带按钮的ListView):
import bb.cascades 1.0
Page {
Container {
id: mainContainer
layout: DockLayout {}
ListView {
id: listView
dataModel: _xmlTest.model
//dataModel: XmlDataModel {
// source: "models/model2.xml"
//}
onDataModelChanged: {
console.log("Data model changed!");
}
listItemComponents: [
ListItemComponent {
type: "user"
StandardListItem {
title: ListItemData.realname
description: ListItemData.name
}
},
ListItemComponent {
type: "option"
StandardListItem {
title: ListItemData.title
}
}
]
}
Button {
text: "Click"
onClicked: {
console.log("Trying to load file");
_xmlTest.setGroupDataModel();
}
verticalAlignment: VerticalAlignment.Bottom
horizontalAlignment: HorizontalAlignment.Center
}
}
}
和我正在尝试加载的XML:
<root>
<user name="myUsername" realname="My Real Name"/>
<option title="Option 1"/>
<option title="Option 2"/>
<option title="Option 3"/>
<option title="Option 4"/>
<option title="Option 5"/>
</root>
答案 0 :(得分:1)
Q_INVOKABLE函数是某种插槽,因此无法返回对象。 您应该找到ListView并将数据放入模型。
答案 1 :(得分:1)
您只需要setGroupDataModel()
为Q_INVOKABLE
- 其他人只是属性访问者。
但是你误解了GroupDataModel。除非模型PROPERTY发生更改,否则您不希望发出onModelChanged()
。在您的情况下,PROPERTY没有改变,所有改变的是 in 属性。因此,我认为你不需要emit onModelChanged()
,它应该将新值作为参数。
问题出在哪里?
您需要检查是否正确地从XML文件中读取数据。
然后你需要阅读GroupDataModel - 如果我正确阅读它,它只会使用'item'和'header'作为项类型,所以ListItemComponents不会是使用
它更容易(并且可以工作;-)如果不使用GroupDataModel而使用XmlDataModel。
这是我的XmlListView.hpp
主要课程(您的XmlTest
课程):
// Default empty project template
#ifndef XmlListView_HPP_
#define XmlListView_HPP_
#include <QObject>
#include <bb/cascades/XmlDataModel>
#include <bb/cascades/DataModel>
namespace bb { namespace cascades { class Application; }}
class XmlListView : public QObject
{
Q_OBJECT
Q_PROPERTY(bb::cascades::DataModel *model READ model NOTIFY onModelChanged);
public:
XmlListView(bb::cascades::Application *app);
virtual ~XmlListView() {}
bb::cascades::DataModel *model();
Q_INVOKABLE void setGroupDataModel();
signals:
void onModelChanged();
private:
bb::cascades::XmlDataModel *m_model;
};
#endif /* XmlListView_HPP_ */
和.cpp:
// Default empty project template
#include "XmlListView.hpp"
#include <bb/cascades/Application>
#include <bb/cascades/QmlDocument>
#include <bb/cascades/AbstractPane>
#include <bb/data/XmlDataAccess>
using namespace bb::cascades;
using namespace bb::data;
XmlListView::XmlListView(bb::cascades::Application *app)
: QObject(app)
{
m_model = new XmlDataModel();
QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this);
qml->setContextProperty("_xmlTest", this);
AbstractPane *root = qml->createRootObject<AbstractPane>();
app->setScene(root);
}
DataModel *
XmlListView::model() {
return m_model;
}
void
XmlListView::setGroupDataModel() {
m_model->setSource(QUrl("models/model.xml"));
}
我的main.qml,和你的一样:
import bb.cascades 1.0
Page {
Container {
id: mainContainer
layout: DockLayout {}
ListView {
id: listView
dataModel: _xmlTest.model
listItemComponents: [
ListItemComponent {
type: "user"
StandardListItem {
title: ListItemData.realname
description: ListItemData.name
}
},
ListItemComponent {
type: "option"
StandardListItem {
title: ListItemData.title
}
}
]
}
Button {
text: "Click"
onClicked: {
_xmlTest.setGroupDataModel()
}
verticalAlignment: VerticalAlignment.Bottom
horizontalAlignment: HorizontalAlignment.Center
}
}
}
.xml模型文件与您的相同。
要真正了解出错的地方,您需要检查来自XmlDataAccess
课程的数据加载。我还没有完全解决这个问题 - 我担心我现在没有时间了 - 但我尝试了,在我的构造函数中:
qDebug() << "==========================================================";
XmlDataAccess xml;
QVariant xmlData = xml.load(QDir::currentPath() + "/app/native/assets/models/model.xml");
if (xml.hasError()) {
qDebug(xml.error().errorMessage().toAscii());
} else {
QVariantList list = xmlData.toList();
qDebug() << "list len = " << list.size();
}
qDebug() << "==========================================================";
看着我的调试日志,我看到了list len = 0
,所以这段代码没有成功地从XML中读取任何内容。正如我所说,我还没有弄清楚如何让它发挥作用。家庭作业? (请在处理时发布)
一切顺利, ç
答案 2 :(得分:0)
如果您真正想要的是将'用户'数据显示为标题,那么您可以在他的答案中使用@craigmj建议的确切代码将您的数据导入模型,但只需更改{的定义即可在main.qml中{1}}使用ListItemComponent
代替Header
。我已经提供了下面的整个StandardListItem
,您应该可以将其放入main.qml中。 ListView
已记录here。
Header