ListView中的XML未更改 我试图用C++实现一个例子,使XML数据模型在我的.qML文件中(当我点击按钮时)发生变化。为此,我将返回一个Qt属性(GroupDataModel)。但是在返回对象之后,ListView没有改变,尽管我看到model属性再次返回 OBS:如果从XML数据模型中加载它,而不是加载C++代码,它就工作了。

ListView中的XML未更改 我试图用C++实现一个例子,使XML数据模型在我的.qML文件中(当我点击按钮时)发生变化。为此,我将返回一个Qt属性(GroupDataModel)。但是在返回对象之后,ListView没有改变,尽管我看到model属性再次返回 OBS:如果从XML数据模型中加载它,而不是加载C++代码,它就工作了。,c++,qml,blackberry-10,blackberry-cascades,C++,Qml,Blackberry 10,Blackberry Cascades,这是我的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(

这是我的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_ */
以及我尝试加载的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>

Q_可调用函数是某种插槽,因此它们无法返回对象。 您应该找到ListView并放置数据模型

  • 在id:objectName:“listview”之后添加QML
  • 在C++中获取listView:listView*listView=root->findChild(“listView”)
  • 设置数据模型:listView->setDataModel(m_模型)
您只需要将
setGroupDataModel()
设置为可调用的
Q\u
——其他只是属性访问器

但是你误解了GroupDataModel。除非模型属性发生更改,否则不希望发出一个
onModelChanged()
。在您的情况下,属性没有更改,更改的只是属性中的值。因此,您不需要
emit onModelChanged()
,我认为它应该将新值作为参数

那么问题出在哪里呢

您需要检查是否正确读取了XML文件中的数据

然后,您需要仔细阅读-如果我阅读正确,它将只使用'item'和'header'作为项目类型,因此不会使用ListItemComponents

如果不使用GroupDataModel而使用

这是我的
XmlListView.hpp
主类(您的
XmlTest
类):

xml模型文件与您的相同

要真正理解哪里出了问题,需要检查从
XmlDataAccess
类加载的ehte数据。我还没有完全解决这个问题——恐怕我现在没有更多的时间了——但我尝试了,在我的构造函数中:

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() << "==========================================================";

qDebug()如果您真正想要的是将“用户”数据显示为标题,那么您可以使用@craigmj在其回答中建议的确切代码将数据放入模型中,但只需将main.qml中的
ListItemComponent
的定义更改为使用
header
,而不是
StandardListItem
。我在下面提供了完整的
列表视图
,您应该可以直接将其放到main.qml中<代码>标题
已记录在案


Q_INVOKABLE不是插槽,它们只是向QML公开的方法。它们可以返回值。没错,问题在于我调用.toList()时解析数据的方式。不知何故,当我们在QML中使用XMLDATAMODEL时,当我从C++代码中解析它时,它就不起作用。但是我还没有弄清楚如何使它与头和项一起工作……如果您使用XMLDataModel,那么您可以区分“用户”和“选项”,尽管这可能不是您的确切意思。。。?您是否希望将“用户”节点作为[n]的indexPath,将选项作为[n,o]的indexPath?这其实并不重要。我想要的是区分作为标题的“用户”和作为标准项的“选项”。我使用的是GroupDataModel,因为当我尝试XmlDataModel时,它没有出现在屏幕上,但我只能使用QVariantList才能使它工作,因为在QVariantList中无法知道节点的名称。
<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>
// 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_ */
// 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"));
}
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
        }

    }
}
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() << "==========================================================";
    ListView {
        id: listView
        dataModel: _xmlTest.model

        onDataModelChanged: {
            console.log("Data model changed!");
        }
        listItemComponents: [
            ListItemComponent {
                type: "user"
                Header {
                    title: ListItemData.realname
                    subtitle: ListItemData.name
                }
            },
            ListItemComponent {
                type: "option"
                StandardListItem {
                    title: ListItemData.title
                }
            }
        ]
    }