Return 从 C++ 到 QML 字符串的 GET 请求响应

Return response of GET request from c++ to QML string

我正在尝试执行一个简单的 GET 请求(使用修改后的用户代理),return 响应 QML 并执行 JSON 解析。

实际上它只有 return 加载完成时的页面内容,但不会 return 到 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();
}

希望我已经很好地解释了我要找的东西。感谢您的帮助。

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

编辑 2015 年 8 月 20 日:添加更新 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

你的问题是思维同步。 connectUrl 不能 return 一个值(它确实没有),因为当它运行时结果不可用。相反,您必须做的是让 ConnectNet class 在数据可用时发出信号。

如果您尝试制作一个执行 return 值的同步包装器,那将是一个可怕的想法:只要接收到结果,QML 引擎就会卡住。您可以通过在适当的时候拔出网络电缆来冻结您的应用程序,或者如果服务器已关闭。用户讨厌它,这是一个可怕的反模式,必须及时消除和劝阻。

这是您的 ConnectNet(请不要 connectNet,会员的小写名称!)class 的样子。请注意,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)
  }
  ...
}