ListView中不会更改XML

时间:2013-01-14 21:28:55

标签: c++ qml blackberry-10 blackberry-cascades

我正在尝试使用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>

3 个答案:

答案 0 :(得分:1)

Q_INVOKABLE函数是某种插槽,因此无法返回对象。 您应该找到ListView并将数据放入模型。

  • 在id:objectName:“listview”
  • 之后添加QML
  • 在C ++中获取listView:ListView * listView = root-&gt; findChild(“listView”);
  • 设置DataModel:listView-&gt; setDataModel(m_model);

答案 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