更新类变量Qt信号和插槽

时间:2016-05-25 17:34:56

标签: c++ qt class

我有以下代码用Q ++填充Qt中的QStringList。当我在GetCountriesList槽中填充我的列表并尝试打印更新的QStringList m_CountriesList时,列表为空。如何确保GetCountriesList槽void方法有效并在GetIndicatorsList()方法中打印正确的值。

   void MainWindow::GetIndicatorsList()
{
    QNetworkAccessManager *networkManager;
    networkManager = new QNetworkAccessManager(this);
    QUrl url("http://api.worldbank.org/countries?per_page=264&format=json");
    QNetworkReply* reply = networkManager->get(QNetworkRequest(url));
    connect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(GetCountriesList(QNetworkReply*)));
    qDebug()<< this->m_CountriesList;

}

void MainWindow::GetCountriesList(QNetworkReply* reply)
{
    if(reply->error() == QNetworkReply::NoError) {


        QString strReply = (QString)reply->readAll();

        QStringList CountriesList;
        QJsonDocument jsonResponse = QJsonDocument::fromJson(strReply.toUtf8());
        QJsonArray JsonArray = jsonResponse.array();
        JsonArray.removeFirst();

        QJsonArray JsonArray2 = JsonArray[0].toArray();

        for (int i = 0; i < JsonArray2.size(); i++) {
            CountriesList.append(JsonArray2.at(i).toObject().value("name").toString());
         }
        //qDebug() << CountriesList;

        this->m_CountriesList = CountriesList;
        qDebug() << this->m_CountriesList;

        }

     else {
        qDebug() << "ERROR";
    }

}

1 个答案:

答案 0 :(得分:1)

你的问题在于:

connect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(GetCountriesList(QNetworkReply*)));

当网络回复完成并发出信号时,该插槽将被称为稍后connect操作非常快,不等待信号执行,只是创建一个连接。

所以当你这样做时

qDebug()<< this->m_CountriesList;

在连接之后,该插槽未被称为尚未

此时数据根本不可用,因为尚未发出信号,并且尚未执行存储国家/地区的代码。

这个答案:https://stackoverflow.com/a/27034939/835629向您展示如何处理这种情况。无论如何,您无法立即返回GetIndicatorsList中的值,因为这会阻止程序执行几秒钟,即发出网络请求并获得答案的时间。

您还可以在数据准备就绪时提供要回调的函数或对象。 Lambda functions可能会帮助你。

例如:

#include <functional>

void MainWindow::GetIndicatorsList(std::function<void(QStringList)> callback)
{
    if (m_CountriesList.length() > 0) {
         callback(m_CountriesList);
         return;
    }
    QNetworkAccessManager *networkManager;
    networkManager = new QNetworkAccessManager(this);
    QUrl url("http://api.worldbank.org/countries?per_page=264&format=json");
    QNetworkReply* reply = networkManager->get(QNetworkRequest(url));
    connect(networkManager, &QNetworkAccessManager::finished, [this,callback](QNetworkReply *reply) { 
         if(reply->error() == QNetworkReply::NoError) {


            QString strReply = (QString)reply->readAll();

            QStringList CountriesList;
            QJsonDocument jsonResponse = QJsonDocument::fromJson(strReply.toUtf8());
            QJsonArray JsonArray = jsonResponse.array();
            JsonArray.removeFirst();

            QJsonArray JsonArray2 = JsonArray[0].toArray();

            for (int i = 0; i < JsonArray2.size(); i++) {
                 CountriesList.append(JsonArray2.at(i).toObject().value("name").toString());
            }
            //qDebug() << CountriesList;

            this->m_CountriesList = CountriesList;
            qDebug() << this->m_CountriesList;
            callback(CountriesList);
        }
        else {
            qDebug() << "ERROR";
        }
    });
}

然后你可以这样称呼它:

mainWindow->GetIndicatorsList([](QStringList list) {
     qDebug() << "Called back! " << list;
});