下载完成后带有结果的QT回调

下载完成后带有结果的QT回调,qt,qt5,qtnetwork,Qt,Qt5,Qtnetwork,我有一个QT应用程序,其中几个不同的子组件需要从internet获取数据。我想要一个Network类来完成所有的网络交互,然后以某种方式通知调用方。我不知道如何使用插槽执行此操作,因此我编写了一个回调解决方案: void Network::downloadFile(QString& urlstr, const std::function<void (QString, QByteArray, QNetworkReply::NetworkError)>& callbac

我有一个QT应用程序,其中几个不同的子组件需要从internet获取数据。我想要一个
Network
类来完成所有的网络交互,然后以某种方式通知调用方。我不知道如何使用插槽执行此操作,因此我编写了一个回调解决方案:

void  Network::downloadFile(QString& urlstr, const std::function<void (QString, QByteArray, QNetworkReply::NetworkError)>& callback) {
    auto processDownload = [&]() {
        QNetworkReply * reply = qobject_cast<QNetworkReply *>(sender());
        QByteArray result;
        QString filename = reply->url().fileName();
        if (reply->error() == QNetworkReply::NoError) { // Success
            result = reply->readAll();
         }
        callback(filename, result, reply->error());
        reply->deleteLater();
    };

    QNetworkReply *reply = nam_->get(QNetworkRequest(QUrl(urlstr)));
    connect(reply, &QNetworkReply::downloadProgress, this, &Network::downloadProgress);
    connect(reply, &QNetworkReply::finished, this, processDownload);
}

这会导致一个断层。如何以QT方式实现这一点?

@chehrlic说得对,您创建的回调函数在被调用之前超出了范围。您的问题不需要以“Qt方式”解决。但是信号和插槽会起作用,所以我会告诉你怎么做

首先,将信号连接到插槽:

void MainWindow::DoNetworkRQ(QString url) {
    connect(&network_, &Network::someSignal, this, &MainWindow::onResult);
    network_.downloadFile(url, f);
}
然后,在网络任务完成时发出信号:

void  Network::downloadFile(QString& urlstr, const std::function<void (QString, QByteArray, QNetworkReply::NetworkError)>& callback) {
    auto processDownload = [&]() {
        QNetworkReply * reply = qobject_cast<QNetworkReply *>(sender());
        QByteArray result;
        QString filename = reply->url().fileName();
        if (reply->error() == QNetworkReply::NoError) { // Success
            result = reply->readAll();
         }
        emit someSignal(filename, result, reply->error());
        reply->deleteLater();
    };

    QNetworkReply *reply = nam_->get(QNetworkRequest(QUrl(urlstr)));
    connect(reply, &QNetworkReply::downloadProgress, this, &Network::downloadProgress);
    connect(reply, &QNetworkReply::finished, this, processDownload);
}
void Network::downloadFile(QString&urlstr,const std::function&callback){
自动进程下载=[&](){
QNetworkReply*reply=qobject_cast(发送方());
QByteArray结果;
QString filename=reply->url().filename();
如果(回复->错误()==QNetworkReply::NoError){//成功
结果=回复->读取全部();
}
发出一些信号(文件名、结果、回复->错误();
回复->删除稍后();
};
QNetworkReply*reply=nam_uu2;->get(QNetworkRequest(qrl(urlstr));
连接(reply,&QNetworkReply::downloadProgress,this,&Network::downloadProgress);
connect(reply,&QNetworkReply::finished,this,processDownload);
}

C++基础知识-您的
回调
变量超出范围。复制它,而只是传递对lambda的引用。我想访问对象实例,所以我不能复制它,对吗?正确的“QT”方法是什么@Chehrlic你能展示一下你是如何调用下载文件的吗?这样我们就可以看到你传递给回调的内容了?@JarMan补充了详细信息“我想访问对象实例,所以我不能复制它,对吗?”-不知道你在说什么,但我说局部变量
callback
超出范围,因为你只通过引用lambda传递它们,因此应用程序会崩溃。请阅读有关lambda捕获的内容。在这种情况下,根本不使用回调,来自网络类的函数
someSignal
将连接到主窗口的
MainWindow::onResult
,以便对其执行任何操作?对,我不使用回调,因为你说你只有在找不到工作机会时才这样做。所以我要告诉你如何让插槽工作。当然,您必须在
网络
类中声明您的信号。然后,只要您的
下载文件
函数完成工作,就会调用
主窗口::onResult
。谢谢,我终于理解了信号和插槽机制了!
void  Network::downloadFile(QString& urlstr, const std::function<void (QString, QByteArray, QNetworkReply::NetworkError)>& callback) {
    auto processDownload = [&]() {
        QNetworkReply * reply = qobject_cast<QNetworkReply *>(sender());
        QByteArray result;
        QString filename = reply->url().fileName();
        if (reply->error() == QNetworkReply::NoError) { // Success
            result = reply->readAll();
         }
        emit someSignal(filename, result, reply->error());
        reply->deleteLater();
    };

    QNetworkReply *reply = nam_->get(QNetworkRequest(QUrl(urlstr)));
    connect(reply, &QNetworkReply::downloadProgress, this, &Network::downloadProgress);
    connect(reply, &QNetworkReply::finished, this, processDownload);
}