0

我正在使用 Blackberry 10 Cascades、QML 和 C++ QT,我正在尝试从我编写的一个小型 php web 服务中获取一些 XML 数据,以加载到我正在使用的 Blackberry 10 Dev Alpha Simulator 的列表中 - 但它是不工作。

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

我从一个涉及常规 http 请求的示例开始,并对其进行了修改以使其适合我的目的(这是一个 http post 请求)。(此代码在文本字段中获取世代编号 (1-5))并打印出该世代的口袋妖怪游戏颜色列表)。

这是我开始使用的 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

这是我的 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

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

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

另外,这是我编写的 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();
    }
}

这是我的 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

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

对于生成参数为 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>"

对于生成参数为 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>"

对于 Generation 参数为 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>"

对于 Generation 参数为 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>"

对于其他任何事情,参数生成是 foo (foo 是占位符):

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

我不太确定,为什么这不起作用。我尝试四处寻找其他示例,看看是否可以使用它来弄清楚如何使我的代码正常工作,但这没有成功。

我知道这个问题很长,但我想提供尽可能多的关于我在做什么的细节,以获得最佳答案。话虽如此,我真的不认为我的 main.cpp 文件是相关的,所以我不会把它放在这里,除非有人要求查看它。

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

<game>yellow</game>

进入

<game title="yellow">yellow</game>

在试图让它在没有 title 属性的情况下使用前者之后,因为我认为这可能会解决我的问题,即使它有点 hackish,但它没有。理想情况下,我想弄清楚如何让它以两种方式工作,在游戏标签中使用和不使用 title 属性。

4

1 回答 1

0

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

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

我不得不从我的 data/model.xml 文件中删除它:

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

并且在文件中只有以下代码:

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

我仍然不确定如何获取 QML 文档中标签之间的数据。现在我在标签中使用带有“title”属性的 ListItemData.title,但我想要开始和结束游戏标签之间的内容。

于 2012-08-24T20:52:08.820 回答