[英]Make XML data show in listItemComponents in Blackberry 10 Cascades QML from C++
I'm working in Blackberry 10 Cascades, QML and C++ QT, and I am trying to get some XML data from a small php webservice I wrote, to load into the list on the Blackberry 10 Dev Alpha Simulator I'm using - but it's not working. 我正在使用Blackberry 10 Cascades,QML和C ++ QT进行工作,并且试图从我编写的一个小型php网络服务中获取一些XML数据,以加载到我正在使用的Blackberry 10 Dev Alpha Simulator的列表中-但这是不工作。
That is the xml data does not load into the ListView of QML document, to show on the screen of the Blackberry Simulator. 也就是说xml数据不会加载到QML文档的ListView中,以显示在Blackberry Simulator的屏幕上。 I need help to get that work.
我需要帮助才能完成这项工作。
I had started with an example that involved a regular http request, and modified it to make it customized to my purposes (which is a http post request). 我从一个涉及常规http请求的示例开始,然后对其进行了修改以使其针对我的目的进行定制(这是一个http post请求)。 (This code takes a generation number (1-5) in the text field) and prints out a list of the colours of the pokemon games from that generation).
(此代码在文本字段中使用世代编号(1-5),并打印出该世代的口袋妖怪游戏的颜色列表)。
This is the QML file I started with: 这是我开始的QML文件:
import bb.cascades 1.0
TabbedPane {
activePane: Page {
actions: [
// An action item that calls the C++ function that retrieves
// the contact list
ActionItem {
title: "Refresh"
onTriggered: app.initiateRequest()
}
]
content: Container {
layout: DockLayout {}
// A list that has two list item components, one for a header
// and one for contact names. The list has an object name so
// that we can set the data model from C++.
ListView {
objectName: "list"
layout: FlowListLayout {
topPadding: 6
rightPadding: 6
bottomPadding: 6
leftPadding: 6
}
// A simple data model is loaded with just a header.
// This will be replaced when we load the real one
// from C++.
dataModel: XmlDataModel {
source: "model.xml"
}
listItemComponents: [
// The header list item displays a title along with a counter
// that displays the number of children
ListItemComponent {
type: "header"
HeaderListItem {
topMargin: 8
title: ListItemData.title
subtitle: (ListItem.initialized ?
ListItem.view.dataModel
.childCount(ListItem.indexPath) : 0);
}
},
// The contact list item displays the name of the contact
ListItemComponent {
type: "contacts"
StandardListItem {
title: ListItemData.title
}
}
]
}
// The activity indicator has an object name set so that
// we can start and stop it from C++
ActivityIndicator {
objectName: "indicator"
layoutProperties: DockLayoutProperties {
verticalAlignment: VerticalAlignment.Fill
horizontalAlignment: HorizontalAlignment.Fill
}
}
} // Ends the root Container
} // Ends the Page
} // Ends the TabbedPane
And this is my QML file: 这是我的QML文件:
import bb.cascades 1.0
TabbedPane {
activePane: Page {
actions: [
// An action item that calls the C++ function that retrieves
// the contact list
ActionItem {
title: "Refresh"
onTriggered: app.initiateRequest(txtGen.text)
}
]
content: Container {
layout: StackLayout {}
Button {
text: "Get Games"
onClicked: app.initiateRequest(txtGen.text)
}
Label {
text: "Enter Generation (1-5)"
}
TextField {
id: txtGen
}
// A list that has two list item components, one for a header
// and one for contact names. The list has an object name so
// that we can set the data model from C++.
ListView {
objectName: "list"
layout: FlowListLayout {
topPadding: 6
rightPadding: 6
bottomPadding: 6
leftPadding: 6
}
// A simple data model is loaded with just a header.
// This will be replaced when we load the real one
// from C++.
dataModel: XmlDataModel {
source: "model.xml"
}
listItemComponents: [
// The header list item displays a title along with a counter
// that displays the number of children
ListItemComponent {
type: "games"
HeaderListItem {
topMargin: 8
title: ListItemData.generation
subtitle: (ListItem.initialized ?
ListItem.view.dataModel
.childCount(ListItem.indexPath) : 0);
}
},
// The contact list item displays the name of the contact
ListItemComponent {
type: "game"
StandardListItem {
title: ListItemData.title
}
}
]
}
// The activity indicator has an object name set so that
// we can start and stop it from C++
ActivityIndicator {
objectName: "indicator"
layoutProperties: DockLayoutProperties {
verticalAlignment: VerticalAlignment.Fill
horizontalAlignment: HorizontalAlignment.Fill
}
}
} // Ends the root Container
} // Ends the Page
} // Ends the TabbedPane
I also have an xml folder stored under assets/model.xml of my projects directory, with the following contents: 我还有一个xml文件夹,存储在我的项目目录的assets / model.xml下,其内容如下:
<?xml version="1.0" encoding="utf-8"?>
<xml>
<games>
</games>
</xml>
Also, here is the App.cpp code I wrote: 另外,这是我编写的App.cpp代码:
#include "app.hpp"
#include <bb/cascades/Application>
#include <bb/cascades/QmlDocument>
#include <bb/cascades/AbstractPane>
#include <bb/cascades/Button>
#include <bb/cascades/TextField>
#include <QDir>
using namespace bb::cascades;
App::App()
{
// Load the QML document and retrieve the root node
QmlDocument *qml = QmlDocument::create("main.qml");
mRoot = qml->createRootNode<AbstractPane>();
// Retrieve the activity indicator from QML so that we can start
// and stop it from C++
mActivityIndicator = mRoot->findChild<ActivityIndicator*>("indicator");
// Retrieve the list so we can set the data model on it once
// we retrieve it
mListView = mRoot->findChild<ListView*>("list");
//mTextField = mRoot->findChild<TextField*>("textField");
//qDebug() << "Generation: " << mTextField->text();
// Expose this class to QML so that we can call its functions from there
qml->setContextProperty("app", this);
// Create a network access manager and connect a custom slot to its
// finished signal
mNetworkAccessManager = new QNetworkAccessManager(this);
Q_ASSERT(connect(mNetworkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*))));
// Displays a warning message if there's an issue connecting the signal
// and slot. This is a good practice with signals and slots as it can
// be easier to mistype a slot or signal definition
//Q_ASSERT(result);
//Q_UNUSED(result);
// Create a file in the application's data directory
mFile = new QFile("data/model.xml");
// Set the scene using the root node
Application::setScene(mRoot);
}
void App::initiateRequest(QString text)
{
// Start the activity indicator
mActivityIndicator->start();
// Create and send the network request
QNetworkRequest request = QNetworkRequest();
request.setUrl(QUrl("http://192.168.1.109/TESTWEBSERVICE/MAKEXML.php")); //https://developer.blackberry.com/cascades/files/documentation/device_platform/networking/model.xml"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QByteArray bytes;
QUrl params;
params.addQueryItem(QString::fromStdString("generation"), text);
bytes = params.encodedQuery();
mNetworkAccessManager->post(request, bytes);
}
void App::requestFinished(QNetworkReply* reply)
{
// Check the network reply for errors
if (reply->error() == QNetworkReply::NoError) {
// Open the file and print an error if the file cannot be opened
if (!mFile->open(QIODevice::ReadWrite))
{
qDebug() << "\n Failed to open file";
return;
}
mFile->resize(0);
// Write to the file using the reply data and close the file
QByteArray xml = reply->readAll();
mFile->write(xml);
qDebug() << xml;
mFile->flush();
mFile->close();
// Create the data model using the contents of the file. The
// location of the file is relative to the assets directory.
XmlDataModel *dataModel = new XmlDataModel();
dataModel->setSource(QUrl("../../../data/model.xml"));
// Set the new data model on the list and stop the activity indicator
mListView->setDataModel(dataModel);
mActivityIndicator->stop();
}
else
{
qDebug() << "\n Problem with the network";
qDebug() << "\n" << reply->errorString();
}
}
And here is my App.h file: 这是我的App.h文件:
#ifndef APP_H
#define APP_H
#include <QObject>
#include <QFile>
#include <bb/cascades/ActivityIndicator>
#include <bb/cascades/ListView>
#include <bb/cascades/XMLDataModel>
#include <bb/cascades/AbstractPane>
#include <bb/cascades/TextField>
using namespace bb::cascades;
/*!
* @brief Application GUI object
*/
class App : public QObject
{
Q_OBJECT
public:
/*!
* Constructor.
*/
App();
/*!
* Initiates the network request.
*/
Q_INVOKABLE void initiateRequest(QString text);
private slots:
/*!
* Handles the network reply.
*/
void requestFinished(QNetworkReply* reply);
private:
AbstractPane *mRoot;
ActivityIndicator *mActivityIndicator;
ListView *mListView;
TextField *mTextField;
QNetworkAccessManager *mNetworkAccessManager;
QFile *mFile;
QString apiKey;
QString apiString;
};
#endif // ifndef APP_H
And the QDebug() stream prints out the following for the generation paramater being 1: QDebug()流为生成参数为1的输出如下:
"<?xml version="1.0" encoding="utf-8"?>
<xml>
<games generation="1">
<game title="green">green</game>
<game title="red">red</game>
<game title="blue">blue</game>
<game title="yellow">yellow</game>
</games>
</xml>"
For generation paramater being 2: 对于一代参数为2:
"<?xml version="1.0" encoding="utf-8"?>
<xml>
<games generation="2">
<game title="gold">gold</game>
<game title="silver">silver</game>
<game title="crystal">crystal</game>
</games>
</xml>"
For generation paramater being 3: 对于一代参数为3:
"<?xml version="1.0" encoding="utf-8"?>
<xml>
<games generation="3">
<game title="ruby">ruby</game>
<game title="sapphire">sapphire</game>
<game title="emerald">emerald</game>
</games>
</xml>"
For Generation paramater being 4: 对于4世代参数:
"<?xml version="1.0" encoding="utf-8"?>
<xml>
<games generation="4">
<game title="perl">perl</game>
<game title="diamond">diamond</game>
<game title="platinum">platinum</game>
</games>
</xml>"
For Generation paramater being 5: 对于第五代参数:
"<?xml version="1.0" encoding="utf-8"?>
<xml>
<games generation="5">
<game title="black">black</game>
<game title="white">white</game>
<game title="black 2">black 2</game>
<game title="white 2">white 2</game>
</games>
</xml>"
For anything else, where paramater generation is foo (foo being a placeholder): 对于其他任何情况,参数生成为foo(foo是占位符):
"<?xml version="1.0" encoding="utf-8"?>
<xml>
<games generation="foo">
</games>
</xml>"
I'm not quite sure, why this isn't working. 我不太确定,为什么这不起作用。 I tried searching around for other examples, to see if I could use it to figure out how to make my code work properly, but that didn't work out.
我尝试搜索其他示例,以查看是否可以使用它来弄清楚如何使我的代码正常工作,但是没有成功。
I know this question is long, but I wanted to provide as much detail about what I was doing, in order to get the best answers. 我知道这个问题很长,但是为了获得最佳答案,我想提供尽可能多的细节。 That being said, I don't really think the my main.cpp file is relevant, so I won't put it here, unless someone asks to see it.
话虽这么说,我真的不认为我的main.cpp文件是相关的,因此除非有人要求查看,否则我不会将其放在此处。
(I added the title attribute to my game tags in my xml code and put the same values as the main data values in those tags, such as turning (我在xml代码中将title属性添加到了游戏标签中,并在这些标签中添加了与主要数据值相同的值,例如
<game>yellow</game>
into 进入
<game title="yellow">yellow</game>
after trying to get it to work with out the title attribute just the former because I thought that might solve my problem, even though it was a bit hackish, but it didn't. 在尝试使其与title属性一起使用之前,是因为前者是因为我认为这可以解决我的问题,即使它有点破烂,但事实并非如此。 Ideally, I want to figure out how to get this to work both ways, with and without the title attribute in the game tags.
理想情况下,我想弄清楚如何在游戏标签中有和没有title属性的情况下使它同时工作。
I found the problem. 我发现了问题。 I had to remove the xml header code from my php webservice,
我必须从php网络服务中删除xml标头代码,
header('Content-type: text/xml');
"<?xml version="1.0" encoding="utf-8"?>
And I had to remove this from my data/model.xml file: 而且我必须从我的data / model.xml文件中删除它:
<?xml version="1.0" encoding="utf-8"?>
And have just this code in the file: 并且在文件中仅包含以下代码:
<xml>
<games>
</games>
</xml>
I'm still not sure how to get the data between the tags in the QML document. 我仍然不确定如何在QML文档中的标签之间获取数据。 Right now I am using ListItemData.title with a "title" attribute in my tags, but I want the content between the opening and closing game tags.
现在,我在标签中使用具有“ title”属性的ListItemData.title,但我希望在开始和结束游戏标签之间添加内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.