PySide 线程和 http 下载 [英] PySide threading and http downloading
问题描述
我很难让这段代码正常工作!!!!当我一步一步调试它时它运行良好,但正常运行时它只是崩溃.最初我使用 QThread 来更新 ImagePreview 像素图,但经过一整天的崩溃和痛苦之后,我改变了方向.现在它可以工作,在上面的场景中使用调试器时,但否则我很难过.请帮我!这段代码有什么问题?我可以使用另一种方法吗?我正在尝试使用从 url 下载的图像不断更新图像预览.
I've had soooo much trouble getting this code to work properly!!!! It runs fine when I debug it step by step, but when running normally it just crashes. Initially I was using a QThread to update the ImagePreview pixmap, but after a whole day of crashes and pain, I changed course. Now it works, in the above scenario when using the debugger, but otherwise I'm stumped. Please help me! What's wrong with this code? Is there another approach I can use? I'm trying to constantly update the image preview with an image downloaded from a url.
import sys
import io
import urllib2
from PySide import QtCore, QtGui, QtNetwork
import time
class QDownloadBuffer(QtCore.QBuffer):
downloadFinished = QtCore.Signal()
def __init__(self):
super(QDownloadBuffer, self).__init__()
self.open(QtCore.QBuffer.ReadWrite)
self.url = QtCore.QUrl("http://www.google.com.au/images/srpr/logo3w.png")
self.manager = QtNetwork.QNetworkAccessManager()
self.request = QtNetwork.QNetworkRequest(self.url)
self.manager.finished.connect(self.onFinished)
def startDownload(self):
print("Starting Download --")
self.reply = self.manager.get(self.request)
self.reply.error[QtNetwork.QNetworkReply.NetworkError].connect(self.onError)
def onFinished(self):
print("Download Finished -- ")
print(self.write(self.reply.readAll()))
self.reply.close()
self.downloadFinished.emit()
def onError(self):
print("oh no there is an error -- ")
print(self.reply.error())
class ImagePreview(QtGui.QWidget):
def __init__(self, parent=None):
super(ImagePreview, self).__init__(parent)
self.setMinimumSize(50, 50)
self.text = None
self.pixmap = None
self.dl_n = 0
def paintEvent(self, paintEvent):
painter = QtGui.QPainter(self)
if(self.pixmap):
painter.drawPixmap(0, 0, self.pixmap)
if(self.text):
painter.setPen(QtCore.Qt.blue)
painter.setFont(QtGui.QFont("Arial", 30))
painter.drawText(self.rect(), QtCore.Qt.AlignCenter, self.text)
def startDownload(self):
self.setText(str(self.dl_n))
self.dl_n += 1
print("Starting Download {0}".format(self.dl_n))
self.db = QDownloadBuffer()
self.connect(self.db, QtCore.SIGNAL("downloadFinished()"), self, QtCore.SLOT("ondownloadFinished()"))
self.db.startDownload()
def ondownloadFinished(self):
self.paintImage()
print("download finished?")
self.db.close()
self.startDownload()
def paintImage(self):
print("Painting")
pixmap = QtGui.QPixmap()
pixmap.loadFromData(self.db.data())
self.setPixmap(pixmap)
def setPixmap(self, pixmap):
self.pixmap = pixmap
self.setMinimumSize(pixmap.width(), pixmap.height())
self.update()
def setText(self, text):
self.text = text
self.update()
class MainWindow(QtGui.QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.imagepreview = ImagePreview()
self.button = QtGui.QPushButton("Start")
self.button.clicked.connect(self.imagepreview.startDownload)
layout = QtGui.QVBoxLayout()
layout.addWidget(self.button)
layout.addWidget(self.imagepreview)
self.setLayout(layout)
if __name__ == "__main__":
import sys
try:
app = QtGui.QApplication(sys.argv)
except RuntimeError:
pass
mainwindow = MainWindow()
mainwindow.show()
sys.exit(app.exec_())
推荐答案
我认为问题在于您正在从插槽(信号处理程序)调用 self.startDownload()
.因此,您不会将控制权返回给 Qt 主循环(或类似的东西).正确的方法是将其称为延迟事件,例如通过 QTimer.singleShot
调用它:
I think the problem is that you are calling self.startDownload()
from slot (signal handler). So you are not returning control to Qt main loop (or something like this). Proper way is to call it as deferred event, e.g. by calling it through QTimer.singleShot
:
def ondownloadFinished(self):
self.paintImage()
print("download finished?")
self.db.close()
QtCore.QTimer.singleShot(0, self.startDownload)
注意 singleShot
和 msec
设置为 0:
Note that singleShot
with msec
set to 0:
QtCore.QTimer.singleShot(0, self.startDownload)
等同于:
QtCore.QMetaObject.invokeMethod(self, 'startDownload', QtCore.Qt.QueuedConnection)
这篇关于PySide 线程和 http 下载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!