PySide线程和http下载

时间:2012-02-08 12:29:02

标签: python qt pyqt pyside

我已经很难让这段代码正常工作!!!!当我逐步调试它时它运行正常,但是当正常运行它只是崩溃。最初我使用QThread来更新ImagePreview像素图,但经过一整天的崩溃和痛苦,我改变了路线。现在它可以工作,在上面使用调试器的情况下,但是否则我很难过。请帮我!这段代码出了什么问题?我可以使用另一种方法吗?我正在尝试使用从网址下载的图片不断更新图像预览。

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_())

1 个答案:

答案 0 :(得分:8)

我认为问题在于你是从插槽(信号处理程序)调用self.startDownload()。所以你没有将控制返回到Qt主循环(或类似的东西)。正确的方法是将其称为延期事件,例如通过QTimer.singleShot调用它:

def ondownloadFinished(self):
    self.paintImage()
    print("download finished?")
    self.db.close()
    QtCore.QTimer.singleShot(0, self.startDownload)

请注意,singleShot msec设置为0:

QtCore.QTimer.singleShot(0, self.startDownload)

与:

相同
QtCore.QMetaObject.invokeMethod(self, 'startDownload',  QtCore.Qt.QueuedConnection)

sourcerelated question