Qt 基于 Qt 示例从 QThread 下载文件不起作用
您好,我构建了简单的示例,删除了所有不相关的代码,只保留有问题的代码 一般来说,我有执行线程的应用程序,在这个线程工作线程中,我放置了应该下载超过30个文件的下载代码,这是基于Qt给出的下载示例,问题是QNetworkAccessManager插槽永远不会调用。
你能告诉我我在这里做错了什么吗?
class MainWindowContainer : public QMainWindow
{
Q_OBJECT
public:
MainWindowContainer(QWidget *parent = 0);
public slots:
void InvokeDownloadThread();
private:
QPushButton *pushButtonInvokeThread;
PhotosDownloadWorker* pm_hotosDownloadWorker;
};
#include <QtGui>
#include "MainWindowContainer.h"
MainWindowContainer::MainWindowContainer(QWidget* parent) :
QMainWindow(parent)
{
pushButtonInvokeThread = new QPushButton(this);
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(pushButtonInvokeThread);
setLayout(layout);
QObject::connect(pushButtonInvokeThread,SIGNAL(clicked()),this, SLOT(InvokeDownloadThread()));
}
void MainWindowContainer::InvokeDownloadThread()
{
pm_hotosDownloadWorker = new PhotosDownloadWorker(this);
pm_hotosDownloadWorker->Execute();
}
class PhotosDownloadWorker : public QThread
{
Q_OBJECT
public :
PhotosDownloadWorker(QObject *parent);
~PhotosDownloadWorker();
void Execute();
void append(const QStringList &urlList);
bool saveToDisk(const QString &filename, QIODevice *data);
QString saveFileName(const QUrl &url);
protected:
void run();
private:
bool m_abort;
QList<QNetworkReply *> currentDownloads;
QFile output;
QNetworkAccessManager* networkMgr ;
public slots:
void downloadFinished(QNetworkReply *reply);
void startNextDownload(const QUrl &url);
};
#include "PhotosDownloadWorker.h"
PhotosDownloadWorker::PhotosDownloadWorker(QObject *parent)
: QThread(parent)
{
m_abort = false;
networkMgr = new QNetworkAccessManager(this);
connect(networkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(downloadFinished(QNetworkReply*)));
}
PhotosDownloadWorker::~PhotosDownloadWorker()
{
m_abort = true;
wait();
}
void PhotosDownloadWorker::Execute()
{
m_abort = false;
start();
}
void PhotosDownloadWorker::run()
{
QStringList m_urlList;
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
// x 30
append(m_urlList);
}
void PhotosDownloadWorker::append(const QStringList &urlList)
{
foreach (QString url, urlList)
{
startNextDownload(QUrl::fromEncoded(url.toLocal8Bit()));
}
}
void PhotosDownloadWorker::startNextDownload(const QUrl &url)
{
QNetworkRequest request(url);
QNetworkReply *reply = networkMgr->get(request);
currentDownloads.append(reply);
}
bool PhotosDownloadWorker::saveToDisk(const QString &filename, QIODevice *data)
{
QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) {
fprintf(stderr, "Could not open %s for writing: %s\n",
qPrintable(filename),
qPrintable(file.errorString()));
return false;
}
file.write(data->readAll());
file.close();
return true;
}
void PhotosDownloadWorker::downloadFinished(QNetworkReply *reply)
{
QUrl url = reply->url();
if (reply->error()) {
fprintf(stderr, "Download of %s failed: %s\n",
url.toEncoded().constData(),
qPrintable(reply->errorString()));
} else {
QString filename = saveFileName(url);
if (saveToDisk(filename, reply))
printf("Download of %s succeeded (saved to %s)\n",
url.toEncoded().constData(), qPrintable(filename));
}
reply->deleteLater();
currentDownloads.removeAll(reply);
if (currentDownloads.isEmpty())
{
this->exit();
}
}
QString PhotosDownloadWorker::saveFileName(const QUrl &url)
{
QString path = url.path();
QString basename = QFileInfo(path).fileName();
if (basename.isEmpty())
basename = "download";
if (QFile::exists(basename)) {
// already exists, don't overwrite
int i = 0;
basename += '.';
while (QFile::exists(basename + QString::number(i)))
++i;
basename += QString::number(i);
}
return basename;
}
//main
#include "MainWindowContainer.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindowContainer mainWindowContainer;
mainWindowContainer.show();
return app.exec();
}
Hi i build simple example striped all irrelevant code and only the problematic code remains
in general i have application that execute thread and inside this thread worker , i placed download code that supposed to download more then 30 files , this based on the Download Example Qt gives , the problem is that the QNetworkAccessManager Slot never invokes .
can you please tell me what im doing wrong here ?
class MainWindowContainer : public QMainWindow
{
Q_OBJECT
public:
MainWindowContainer(QWidget *parent = 0);
public slots:
void InvokeDownloadThread();
private:
QPushButton *pushButtonInvokeThread;
PhotosDownloadWorker* pm_hotosDownloadWorker;
};
#include <QtGui>
#include "MainWindowContainer.h"
MainWindowContainer::MainWindowContainer(QWidget* parent) :
QMainWindow(parent)
{
pushButtonInvokeThread = new QPushButton(this);
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(pushButtonInvokeThread);
setLayout(layout);
QObject::connect(pushButtonInvokeThread,SIGNAL(clicked()),this, SLOT(InvokeDownloadThread()));
}
void MainWindowContainer::InvokeDownloadThread()
{
pm_hotosDownloadWorker = new PhotosDownloadWorker(this);
pm_hotosDownloadWorker->Execute();
}
class PhotosDownloadWorker : public QThread
{
Q_OBJECT
public :
PhotosDownloadWorker(QObject *parent);
~PhotosDownloadWorker();
void Execute();
void append(const QStringList &urlList);
bool saveToDisk(const QString &filename, QIODevice *data);
QString saveFileName(const QUrl &url);
protected:
void run();
private:
bool m_abort;
QList<QNetworkReply *> currentDownloads;
QFile output;
QNetworkAccessManager* networkMgr ;
public slots:
void downloadFinished(QNetworkReply *reply);
void startNextDownload(const QUrl &url);
};
#include "PhotosDownloadWorker.h"
PhotosDownloadWorker::PhotosDownloadWorker(QObject *parent)
: QThread(parent)
{
m_abort = false;
networkMgr = new QNetworkAccessManager(this);
connect(networkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(downloadFinished(QNetworkReply*)));
}
PhotosDownloadWorker::~PhotosDownloadWorker()
{
m_abort = true;
wait();
}
void PhotosDownloadWorker::Execute()
{
m_abort = false;
start();
}
void PhotosDownloadWorker::run()
{
QStringList m_urlList;
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
m_urlList.append("http://....xxxx......jpg");
// x 30
append(m_urlList);
}
void PhotosDownloadWorker::append(const QStringList &urlList)
{
foreach (QString url, urlList)
{
startNextDownload(QUrl::fromEncoded(url.toLocal8Bit()));
}
}
void PhotosDownloadWorker::startNextDownload(const QUrl &url)
{
QNetworkRequest request(url);
QNetworkReply *reply = networkMgr->get(request);
currentDownloads.append(reply);
}
bool PhotosDownloadWorker::saveToDisk(const QString &filename, QIODevice *data)
{
QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) {
fprintf(stderr, "Could not open %s for writing: %s\n",
qPrintable(filename),
qPrintable(file.errorString()));
return false;
}
file.write(data->readAll());
file.close();
return true;
}
void PhotosDownloadWorker::downloadFinished(QNetworkReply *reply)
{
QUrl url = reply->url();
if (reply->error()) {
fprintf(stderr, "Download of %s failed: %s\n",
url.toEncoded().constData(),
qPrintable(reply->errorString()));
} else {
QString filename = saveFileName(url);
if (saveToDisk(filename, reply))
printf("Download of %s succeeded (saved to %s)\n",
url.toEncoded().constData(), qPrintable(filename));
}
reply->deleteLater();
currentDownloads.removeAll(reply);
if (currentDownloads.isEmpty())
{
this->exit();
}
}
QString PhotosDownloadWorker::saveFileName(const QUrl &url)
{
QString path = url.path();
QString basename = QFileInfo(path).fileName();
if (basename.isEmpty())
basename = "download";
if (QFile::exists(basename)) {
// already exists, don't overwrite
int i = 0;
basename += '.';
while (QFile::exists(basename + QString::number(i)))
++i;
basename += QString::number(i);
}
return basename;
}
//main
#include "MainWindowContainer.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindowContainer mainWindowContainer;
mainWindowContainer.show();
return app.exec();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
尽管您在代码中调用“networkMgr->get(request)”,但您的线程可能会在实际下载开始之前退出。尝试将“exec()”调用放在“QThread::run()”方法的最底部,以进入 QNetworkAccessManager 需要能够工作的线程中的事件循环。这也将防止线程过早完成其执行。你的代码看起来像这样:
Despite you call "networkMgr->get(request)" in your code, your thread probably exits before the actual download starts. Try to put "exec()" call at the very bottom of your "QThread::run()" method to enter the event loop in your thread that QNetworkAccessManager requires to be able to work. Also that would prevent the thread from finishing its execution too early. Your code would look like this:
我认为如果参数列表不匹配,它甚至不会将信号连接到插槽。请参阅调试器输出以获取有关运行时的警告(应用程序输出选项卡)。
因此,处理错误不是
通过
QNetworkReply 的
error
来完成的信号。在获取
后,您就可以连接到信号。I think it wouldn't even connect the signal to the slot if the parameter lists are mismatched. See the debugger output for a warning about that at runtime (application output tab).
So, instead of
do
Handling errors is done via QNetworkReply's
error
signal. Right after youget
you can connect to the signal.