返回从c ++到QML字符串

时间:2015-08-19 14:35:53

标签: qt qml qtquick2

我试图做一个简单的GET请求(使用修改后的User-Agent),返回对QML的响应并进行JSON解析。

实际上它只在加载完成时返回页面内容,但它不会将其返回到QML。

抱歉这个菜鸟问题。我是这种语言的新手,我正在努力学习它:)

这是我的代码:

Home.qml

function getRequest() {

[...]
console.log('Request...')
var jsonResult = JSON.parse(connectNet.connectUrl("http://myURL.com/index.php").toString())

lbOutput.text = jsonResult.predictions[0].description.toString()
    }
}

connectnet.cpp

#include "connectnet.h"
#include "stdio.h"
#include <QDebug>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QNetworkAccessManager>
#include <QUrl>


connectNet::connectNet(QObject *parent) : QObject(parent)
{
}

void connectNet::connectUrl(QString url)
{    
    QNetworkAccessManager *manager = new QNetworkAccessManager();
    QNetworkRequest request;
    QNetworkReply *reply = NULL;

    request.setUrl(QUrl(url));
    request.setRawHeader( "User-Agent" , "FAKE USER AGENT HERE" );

    reply = manager->get(request);
    connect(manager, SIGNAL(finished(QNetworkReply*)), this,
                     SLOT(replyFinished(QNetworkReply*)));
}    

QString connectNet::replyFinished(QNetworkReply *reply)
{
   return reply->readAll();
}

appname.cpp

#ifdef QT_QML_DEBUG
#include <QtQuick>

#endif

#include <sailfishapp.h>
#include "connectnet.h"


int main(int argc, char *argv[])
{
    //INIT SETTINGS

    QGuiApplication *app = SailfishApp::application(argc, argv);
    QQuickView *view = SailfishApp::createView();
    connectNet ConnectNet;
    view->rootContext()->setContextProperty("connectNet", &ConnectNet);
    view->setSource(SailfishApp::pathTo("qml/APPNAME.qml"));
    view->showFullScreen();
    app->exec();
}

希望我能很好地解释我在寻找什么。谢谢你的帮助。

=============================================== =====

编辑20/08/2015:添加了更新的connectnet.h

    #ifndef CONNECTNET_H
    #define CONNECTNET_H

    #include <QObject>
    #include <QNetworkReply>
    #include <QDebug>
    #include <QNetworkRequest>
    #include <QNetworkReply>
    #include <QNetworkAccessManager>
    #include <QUrl>

class ConnectNet : public QObject
{
    Q_OBJECT
    QNetworkAccessManager m_manager;
public:
  ConnectNet(QObject * parent = 0) : QObject(parent) {
      connect(&m_manager, &QNetworkAccessManager::finished,
      [this](QNetworkReply * reply) {
        if (reply->error() == QNetworkReply::NoError)
          emit replyAvailable(QString::fromUtf8(reply->readAll()));
      });

   }
signals:
    void replyAvailable(const QString & reply);
public slots:
    void sendRequest(const QString url) {
        QNetworkRequest request;
        request.setUrl(QUrl(url));
        request.setRawHeader("User-Agent", "MyLittleAgent");
        m_manager.get(request);
    }
};

    #endif // CONNECTNET_H

这段代码会产生很多错误:((下面的截图)

      connect(&m_manager, &QNetworkAccessManager::finished,
      [this](QNetworkReply * reply) {
        if (reply->error() == QNetworkReply::NoError)
          emit replyAvailable(QString::fromUtf8(reply->readAll()));
      });

编译错误:http://i.stack.imgur.com/30vWn.jpg

1 个答案:

答案 0 :(得分:5)

你的问题是你同步思考。 connectUrl无法返回值(并且它不会返回),因为当它运行时,结果不可用。相反,你必须做的是ConnectNet类在数据可用时发出信号。

如果您尝试制作一个确实返回值的同步包装器,那将是一个可怕的想法:只要接收到结果,QML引擎就会被卡住。您可以在合适的时刻拉动网络电缆,或者如果服务器已关闭,则可以冻结您的应用程序。用户讨厌这一点,而且这是一个可怕的反模式,必须适当地消除和劝阻。

以下是ConnectNet(请,不是connectNet,小写名称适用于成员!)类可以查看的内容。请注意,QNetworkAccessManager实例不需要是指针。

class ConnectNet : public QObject {
  Q_OBJECT
  QNetworkAccessManager m_manager;
public:
  ConnectNet(QObject * parent = 0) : QObject(parent) {
    connect(&m_manager, &QNetworkAccessManager::finished, 
    [this](QNetworkReply * reply) {
      if (reply->error() == QNetworkReply::NoError) 
        emit replyAvailable(QString::fromUtf8(reply->readAll()));
    });
  }
  Q_SLOT void sendRequest(const QString & url) {
    auto request = QNetworkRequest(QUrl(url));
    request.setRawHeader("User-Agent", "MyLittleAgent");
    m_manager.get(request);
  }
  Q_SIGNAL void replyAvailable(const QString & reply);
};

由于connectNet实例实例在全局QML上下文中作为属性公开,因此您可以按如下方式连接到其信号:

function getRequest() {
  connectNet.sendRequest("http://myURL.com/index.php")
}

function resultHandler(result) {
  var jsonResult = JSON.parse(result.toString())
  lbOutput.text = jsonResult.predictions[0].description.toString()
}

Rectangle { // or any other item
  Component.onCompleted: {
    connectNet.replyAvailable.connect(resultHandler)
  }
  ...
}