python - PySide 线程和 http 下载

标签 python qt pyqt pyside

让这段代码正常工作我遇到了很多麻烦!!!!我一步步调试的时候运行的很好,但是正常运行的时候就崩溃了。最初我使用 QThread 来更新 ImagePreview 像素图,但在一整天的崩溃和痛苦之后,我改变了路线。现在它可以工作了,在上面的场景中使用调试器时,但我很难过。请帮我!这段代码有什么问题?我可以使用另一种方法吗?我正在尝试使用从 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 调用它:

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

请注意 singleShotmsec 设置为 0:

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

等同于:

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

( source , related question )

关于python - PySide 线程和 http 下载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9193323/

相关文章:

python - 将每月数据分组到数据框中以显示行小计

c++ - 是否可以对基类非 QObject 类的虚函数进行槽化

python - 多个 PyQt5.QtWidgets.QApplication 对象的段错误

python - 如何将QLineEdit背景变成进度条

python - PyQt QWizard 验证和按钮覆盖

python - 一个音符的录制音频会产生多个起始时间

类 Python 语言的 Python 解析器

python - Pandas 使用 read_sql_table 占用过多内存

c++ - QCamera 获取分辨率和原始帧

qt - Qt5 中仍然需要 "public slots:"部分吗?