使XML数据显示在BlackBerry 10中的listItemComponents中Cascades从C ++的QML [英] Make XML data show in listItemComponents in Blackberry 10 Cascades QML from C++

查看:246
本文介绍了使XML数据显示在BlackBerry 10中的listItemComponents中Cascades从C ++的QML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Blackberry 10 Cascades,QML和C ++ QT工作,我试图从我写的一个小的php webservice获取一些XML数据,加载到Blackberry 10 Dev Alpha模拟器的列表我使用 - 但它不工作。



这是xml数据没有加载到QML文档的ListView,显示在黑莓模拟器的屏幕上。我需要帮助才能完成这项工作。



我开始了一个例子,涉及一个常规的http请求,并修改它,使其根据我的目的(这是一个http post请求)。 (此代码在文本字段中使用代数(1-5)),并打印出该一代的小宠物游戏的颜色列表。



是我开始的QML文件:

  import bb.cascades 1.0 

TabbedPane {
activePane:页面{
操作:[
//调用检索
的C ++函数的操作项目//联系人列表
ActionItem {
title:刷新
onTriggered:app.initiateRequest()
}
]
content:Container {
layout:DockLayout {}

具有两个列表项组件的列表,一个用于标题
//,一个用于联系人名称。该列表有一个对象名称所以
//,我们可以从C ++设置数据模型。
ListView {
objectName:list
layout:FlowListLayout {
topPadding:6
rightPadding:6
bottomPadding:6
leftPadding: 6
}
//一个简单的数据模型只加载一个头。
//当我们从C ++加载真正的
//时,这将被替换。
dataModel:XmlDataModel {
source:model.xml
}

listItemComponents:[
//标题列表项显示一个标题一个计数器
//显示子项数
ListItemComponent {
type:header
HeaderListItem {
topMargin:8
title:ListItemData。 title
subtitle:(ListItem.initialized?
ListItem.view.dataModel
.childCount(ListItem.indexPath):0);
}
//联系人列表项显示联系人的名称
ListItemComponent {
type:contacts
StandardListItem {
title:ListItemData.title
}
}
]
}
//活动指示器设置的对象名称为
//可以从C ++中启动和停止它
ActivityIndi​​cator {
objectName:indicator
layoutProperties:DockLayoutProperties {
verticalAlignment:VerticalAlignment.Fill
horizo​​ntalAlignment:Horizo​​ntalAlignment.Fill
}
}
} //结束根容器
} //结束页面
} //结束TabbedPane



这是我的QML文件:

  import bb.cascades 1.0 

TabbedPane {
activePane:Page {
actions:[
//调用C ++函数检索
/ /联系人列表
ActionItem {
title:Refresh
onTriggered:app.initiateRequest(txtGen.text)
}
]
content:Container {
layout:StackLayout {}

Button {
text:Get Games
onClicked:app.initiateRequest(txtGen.text)
}

标签{
text:输入Generation(1-5)
}

TextField {
id:txtGen
}

//具有两个列表项组件的列表,一个用于标题
//,一个用于联系人名称。该列表有一个对象名称所以
//,我们可以从C ++设置数据模型。
ListView {
objectName:list
layout:FlowListLayout {
topPadding:6
rightPadding:6
bottomPadding:6
leftPadding: 6
}
//一个简单的数据模型只加载一个头。
//当我们从C ++加载真正的
//时,这将被替换。
dataModel:XmlDataModel {
source:model.xml
}

listItemComponents:[
//标题列表项显示一个标题一个计数器
//显示子项数
ListItemComponent {
type:games
HeaderListItem {
topMargin:8
title:ListItemData。生成
subtitle:(ListItem.initialized?
ListItem.view.dataModel
.childCount(ListItem.indexPath):0);
}
}联系人列表项显示联系人的姓名
ListItemComponent {
type:game
StandardListItem {
title:ListItemData.title
}
}
]
}
//活动指示器设置的对象名称为
//可以从C ++中启动和停止它
ActivityIndi​​cator {
objectName:indicator
layoutProperties:DockLayoutProperties {
verticalAlignment:VerticalAlignment.Fill
horizo​​ntalAlignment:Horizo​​ntalAlignment.Fill
}
}
} //结束根容器
} //结束页面
} //结束TabbedPane



我还有一个xml文件夹存储在我的项目目录的assets / model.xml下,
包含以下内容:

 <?xml version =1.0encoding =utf-8?& 
< xml>
< games>
< / games>
< / xml>

此外,这里是我写的App.cpp代码:

  #includeapp.hpp

#include< bb / cascades / Application>
#include< bb / cascades / QmlDocument>
#include< bb / cascades / AbstractPane>
#include< bb / cascades / Button>
#include< bb / cascades / TextField>
#include< QDir>

使用命名空间bb :: cascades;

App :: App()
{
//加载QML文档并检索根节点
QmlDocument * qml = QmlDocument :: create(main。 qml);
mRoot = qml-> createRootNode< AbstractPane>();

//从QML获取活动指示符,以便我们可以从C ++启动
//并停止它
mActivityIndi​​cator = mRoot-> findChild< ActivityIndi​​cator *>指示符);

//检索列表,以便我们可以在其上设置数据模型
//我们检索它
mListView = mRoot-> findChild< ListView *>列表);

// mTextField = mRoot-> findChild< TextField *>(textField);

// qDebug()<< Generation:<< mTextField-> text();

//将这个类公开给QML,以便我们可以从那里调用它的函数
qml-> setContextProperty(app,this);

//创建一个网络访问管理器并将一个自定义插槽连接到它的
//完成信号
mNetworkAccessManager = new QNetworkAccessManager(this);

Q_ASSERT(connect(mNetworkAccessManager,SIGNAL(finished(QNetworkReply *)),this,SLOT(requestFinished(QNetworkReply *)))));

//如果连接信号
//和插槽有问题,则显示警告消息。这是一个好的做法与信号和插槽,因为它可以
//更容易错误的插槽或信号定义
// Q_ASSERT(result);
// Q_UNUSED(result);

//在应用程序的数据目录中创建一个文件
mFile = new QFile(data / model.xml);

//使用根节点设置场景
Application :: setScene(mRoot);
}

void App :: initiateRequest(QString text)
{
//开始活动指示器
mActivityIndi​​cator-> start();

//创建和发送网络请求
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 *回复)
{
//检查网络回应的错误
if(reply-> error()== QNetworkReply :: NoError){

打开文件并打印一个错误,如果文件不能打开

if(!mFile-> open(QIODevice :: ReadWrite))
{
qDebug()< <\ n无法打开文件;
return;
}

mFile-> resize(0);

使用回复数据写入文件并关闭文件
QByteArray xml = reply-> readAll();
mFile-> write(xml);
qDebug()<< xml;

mFile-> flush();
mFile-> close();

//使用文件的内容创建数据模型。
//文件的位置是相对于assets目录的。
XmlDataModel * dataModel = new XmlDataModel();

dataModel-> setSource(QUrl(../../../ data / model.xml));

//在列表上设置新的数据模型并停止活动指示器
mListView-> setDataModel(dataModel);
mActivityIndi​​cator-> stop();
}
else
{
qDebug()<< \\\
网络问题;
qDebug()<< \\\
< reply-> errorString();
}
}

这里是我的App.h文件:

  #ifndef APP_H 
#define APP_H

#include< QObject>
#include< QFile>
#include< bb / cascades / ActivityIndi​​cator>
#include< bb / cascades / ListView>
#include< bb / cascades / XMLDataModel>
#include< bb / cascades / AbstractPane>
#include< bb / cascades / TextField>

使用命名空间bb :: cascades;

/ *!
* @brief应用程序GUI对象
* /
类应用程序:public QObject
{
Q_OBJECT

public:
/ *!
*构造函数。
* /
App();
/ *!
*启动网络请求。
* /
Q_INVOKABLE void initiateRequest(QString text);

私人插槽:
/ *!
*处理网络回复。
* /
void requestFinished(QNetworkReply * reply);

private:
AbstractPane * mRoot;
ActivityIndi​​cator * mActivityIndi​​cator;
ListView * mListView;
TextField * mTextField;
QNetworkAccessManager * mNetworkAccessManager;
QFile * mFile;
QString apiKey;
QString apiString;
};

#endif // ifndef APP_H

QDebug对于生成参数为1,输出以下内容:

 <?xml version =1.0encoding =utf-8 > 
< xml>
< games generation =1>
< game title =green> green< / game>
< ; game title =red> red< / game>
< game title =blue> blue< / game>
< game title =yellow> game>
< / games>
< / xml>

对于生成参数为2:

 <?xml version =1.0encoding =utf-8?> 
< xml>
< games generation =2> ;
< game title =gold> gold< / game>
< game title =silver> silver< / game>
< game title =crystal > crystal< / game>
< / games>
< / xml&

对于生成参数为3:

 <?xml version =1.0encoding =utf-8?> 
< xml>
< games generation =3> ;
< game title =ruby> ruby​​< / game>
< game title =sapphire> sapphire< / game>
< game title =emerald > emerald< / game>
< / games>
< / xml>

对于生成参数为4:

 <?xml version =1.0encoding =utf-8?> 
< xml>
< games generation =4> ;
< game title =perl> perl< / game>
< game title =diamond> diamond< / game>
< game title =platinum > platinum< / game>
< / games>
< / xml&

对于生成参数为5:

 <?xml version =1.0encoding =utf-8?> 
< xml>
< games generation =5 ;
< game title =black> black< / game>
< game title =white> white< / game>
< game title = 2> black 2< / game>
< game title =white 2> white 2< / game>
< / games>
< / xml>

对于别的,其中参数生成是foo(foo是一个占位符):

 <?xml version =1.0encoding =utf-8?> 
< xml>
< games generation =foo>
< / games>
< / xml>

我不太确定,为什么这不工作。我试着搜索其他的例子,看看是否可以使用它来弄清楚如何使我的代码正常工作,但没有成功。



我知道这个问题很长,但我想提供关于我在做什么的细节,以获得最好的答案。也就是说,我不认为我的main.cpp文件是相关的,所以我不会把它放在这里,除非有人要求看到它。



(我在我的xml代码中向我的游戏标签添加了title属性,并在这些标签中设置了与主要数据值相同的值,例如转动

 < game> yellow< / game> 

 < game title =yellow> yellow< / game> 

试图让它工作的标题属性只是前者,因为我认为这可能解决我的问题,即使它是一个有点hackish,但它没有。理想情况下,我想要弄清楚如何在游戏标签中使用和不使用title属性。

解决方案

p>我发现了问题。我不得不从我的php webservice中删除xml头部代码,

  :text / xml'); 
<?xml version =1.0encoding =utf-8?>

我必须从data / model.xml文件中删除:

 <?xml version =1.0encoding =utf-8?> 

在文件中只有这个代码:

 < xml> 
< games>
< / games>
< / xml>

我还不知道如何在QML文档中的标签之间获取数据。现在我使用ListItemData.title在我的标签中有一个title属性,但我想要的开始和结束游戏标签之间的内容。


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.

That is the xml data does not load into the ListView of QML document, to show on the screen of the 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). (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).

This is the QML file I started with:

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:

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 version="1.0" encoding="utf-8"?>
<xml>
  <games>
  </games>
</xml>

Also, here is the App.cpp code I wrote:

#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:

#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:

"<?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:

"<?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:

"<?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:

"<?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):

"<?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.

(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

<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. Ideally, I want to figure out how to get this to work both ways, with and without the title attribute in the game tags.

解决方案

I found the problem. I had to remove the xml header code from my php webservice,

header('Content-type: text/xml');
"<?xml version="1.0" encoding="utf-8"?>

And I had to remove this from my data/model.xml file:

<?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. 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.

这篇关于使XML数据显示在BlackBerry 10中的listItemComponents中Cascades从C ++的QML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆