QThread 中的 Qt 信号和槽
Posted
技术标签:
【中文标题】QThread 中的 Qt 信号和槽【英文标题】:Qt Signals and slots in a QThread 【发布时间】:2012-11-03 17:43:18 【问题描述】:我目前在 Qt 线程上遇到问题。
我必须在 QThread 中上传文件列表,但显然一次上传不起作用和/或我的插槽从未被调用。如果我把方法放在线程之外,它就可以完美地工作。
这里是 run() 方法:
void UploadThread::run()
for (int i = 0; i < Window::_listUpload.size(); i++)
qDebug() << Window::_listUpload[i].getPath();
this->sendFile(Window::_listUpload[i].getPath());
这里是 sendFile() 方法:
void UploadThread::sendFile(const QString & path)
QFreeDesktopMime mime;
QNetworkAccessManager *manager = new QNetworkAccessManager;
QFileInfo fInfo(path);
QNetworkRequest request(QUrl("http://my-url/"));
QNetworkReply *reply;
QString bound = "---------------------------723690991551375881941828858";
QByteArray data(QString("--"+bound+"\r\n").toAscii());
data += "Content-Disposition: form-data; name=\"action\"\r\n\r\n";
data += "\r\n";
data += QString("--" + bound + "\r\n").toAscii();
data += "Content-Disposition: form-data; name=\"file\"; filename=\""+fInfo.fileName()+"\"\r\n";
data += "Content-Type: "+mime.fromFile(path)+"\r\n\r\n";
QFile file(fInfo.absoluteFilePath());
file.open(QIODevice::ReadOnly);
data += file.readAll();
data += "\r\n";
data += QString("--" + bound + "\r\n").toAscii();
data += QString("--" + bound + "\r\n").toAscii();
data += "Content-Disposition: form-data; name=\"desc\"\r\n\r\n";
data += "Description for my image here :)\r\n";
data += "\r\n";
request.setRawHeader(QString("Accept-Encoding").toAscii(), QString("gzip,deflate").toAscii());
request.setRawHeader(QString("Content-Type").toAscii(),QString("multipart/form-data; boundary=" + bound).toAscii());
request.setRawHeader(QString("Content-Length").toAscii(), QString::number(data.length()).toAscii());
reply = manager->post(request, data);
QObject::connect(reply, SIGNAL(uploadProgress(qint64,qint64)), currentThread(), SLOT(receiveUploadProgress(qint64, qint64)));
QObject::connect(manager, SIGNAL(finished(QNetworkReply*)), currentThread(), SLOT(uploadFinished(QNetworkReply*)));
这是我的插槽:
void UploadThread::uploadFinished(QNetworkReply *reply)
_isFinished = true;
void UploadThread::receiveUploadProgress(qint64 bytesSent, qint64 bytesTotal)
qDebug() << bytesSent << " " << bytesTotal;
您在我的代码中发现问题了吗? 谢谢。
【问题讨论】:
【参考方案1】:好的,我明白了。
对于每次上传,我需要使用 exec() 启动 QEventLoop,并且在上传结束时我必须使用 exit() 来完成 QEventLoop。它现在就像一个魅力。
【讨论】:
【参考方案2】:您似乎在您的sendFile()
方法中调用了QObject::connect()
。
QObject::connect()
使用插槽方法连接信号。可以使用emit signalName()
之类的方式触发信号。
在您的示例中,您的 UploadThread 标头应如下所示:
class UploadThread: public QThread
...
signals:
void uploadProgress(int sent, int total);
void uploadFinished(QNetworkReply *reply);
不要实现信号,它们是由 Qt 自动实现的。
在 sendFile() 中,调用它们即可:
...
emit uploadProgress(sent, total);
...
在您的主线程(=gui 线程)中,您应该有一个具有处理信号插槽的类(您当前的 uploadFinished() 和 recieveUploadProgress() 方法)。如果您想更新 GUI,重要的是它们在 GUI 线程中执行。
最后你必须连接它们(连接并不意味着调用它们)并开始上传。
UploadThread *uploadThread = new UploadThread();
connect(uploadThread, SIGNAL(uploadProgress(...)), objectInGuiThread, SLOT(actualUploadProgressSlot(...)));
uploadThread.start()
查看 Qt 的 Signal & Slot 文档,了解有关如何使用它们的更多信息。
【讨论】:
我不必重新实现uploadProgress() 和finished() 信号,它们分别由QNetworkReply 和QNetworkAccessManager 实现。我不必手动发出它们。所以,我的代码应该可以工作,不是吗?以上是关于QThread 中的 Qt 信号和槽的主要内容,如果未能解决你的问题,请参考以下文章