2012-02-08 79 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