2012-02-08 81 views
4

我已经很难让这段代码正常工作!!!!当我一步一步地调试它时,它运行良好,但是在正常运行时它只会崩溃。最初我使用QThread来更新ImagePreview pixmap,但在经历了整整一天的崩溃和痛苦之后,我改变了方向。现在,它在上述使用调试器的情况下工作,但否则我会难倒。请帮帮我!这段代码有什么问题?我可以使用另一种方法吗?我试图不断更新图像预览与从网址下载的图像。PySide线程和HTTP下载

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

回答

8

我认为问题是,你在呼唤从插槽(信号处理)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) 

sourcerelated question

+0

由于一堆!它现在有效! – kellpossible 2012-02-08 23:39:57

+0

只是一个简单的问题,你认为使用单独的线程来执行这样的操作会更明智吗?我非常努力地使用线程来实现它,但是没有运气,但是如果它值得的话,我会用这个新知识给它另一个镜头。 – kellpossible 2012-02-08 23:41:35

+2

@kellpossible,你也可以用线程来完成。示例http://pastebin.com/b4MD5jKh。但我不知道你的情况会更好。 – reclosedev 2012-02-09 08:53:47