2011-07-27 5 views
3

제 GUI에서 저는 많은 것들을 중간에 다운로드해야합니다. 나는 그것을하기 위해 urllib을 사용한다. 물론 문제는 모든 것이 다운로드 될 때까지 GUI가 멈추게됩니다.pyqt4의 스레딩

내 코드는 위의 함수는 다운로드 코드를 갖는 것을 특징으로

QtCore.QObject.connect(self.UI.commandLinkButton_2 , QtCore.SIGNAL("clicked()") , self.addStoryToHistory) 

를 다음과 같은 것입니다.

이 중에 공유 데이터를 보내는 것과 프로세스가 단지 데이터를 한 위치로 다운로드하는 것과 같은 것은 없습니다.

GUI를 정지시키지 않는 가장 간단한 방법은 무엇입니까? multiprocessing 또는 QThreads을 사용해야합니까?

은 아무도 .... 내가 그것을 지적하시기 바랍니다 않는 쉬운 방법이 있다면 그렇게 매우 복잡 할을하지 않으 .... 몇 가지 링크에

덕분에 많이 날 포인트 ...

답변

5

여기 난 그냥 다시 도심 PyQt는에서 HTTP 예제를 사용하여 몇 달에 작업 한 프로젝트에서 제거 한 예입니다 :

이 다른 질문을 참조하십시오. Riverbank 웹 사이트에서 SIP를 다운로드합니다.

urllib 대신 QtNetwork에서 QHttp을 사용하고 진행률 막대를 dataReadProgress 신호에 연결했습니다. 이렇게하면 응답 성있는 GUI는 물론 파일을 안정적으로 다운로드 할 수 있습니다.

from PyQt4.QtCore import QUrl, QFileInfo, QFile, QIODevice 
from PyQt4.QtGui import QApplication, QDialog, QProgressBar, QLabel, QPushButton, QDialogButtonBox, \ 
        QVBoxLayout, QMessageBox 
from PyQt4.QtNetwork import QHttp 

url_to_download = 'http://www.riverbankcomputing.co.uk/static/Downloads/sip4/sip-4.12.3.zip' 

class Downloader(QDialog): 
    def __init__(self, parent=None): 
     super(Downloader, self).__init__(parent) 

     self.httpGetId = 0 
     self.httpRequestAborted = False 
     self.statusLabel = QLabel('Downloading %s' % url_to_download) 
     self.closeButton = QPushButton("Close") 
     self.closeButton.setAutoDefault(False) 
     self.progressBar = QProgressBar() 

     buttonBox = QDialogButtonBox() 
     buttonBox.addButton(self.closeButton, QDialogButtonBox.RejectRole) 

     self.http = QHttp(self) 
     self.http.requestFinished.connect(self.httpRequestFinished) 
     self.http.dataReadProgress.connect(self.updateDataReadProgress) 
     self.http.responseHeaderReceived.connect(self.readResponseHeader) 
     self.closeButton.clicked.connect(self.cancelDownload) 

     mainLayout = QVBoxLayout() 
     mainLayout.addWidget(self.statusLabel) 
     mainLayout.addWidget(self.progressBar) 
     mainLayout.addWidget(buttonBox) 
     self.setLayout(mainLayout) 

     self.setWindowTitle('Download Example') 
     self.downloadFile() 

    def downloadFile(self): 
     url = QUrl(url_to_download) 
     fileInfo = QFileInfo(url.path()) 
     fileName = fileInfo.fileName() 

     if QFile.exists(fileName): 
      QFile.remove(fileName) 

     self.outFile = QFile(fileName) 
     if not self.outFile.open(QIODevice.WriteOnly): 
      QMessageBox.information(self, 'Error', 
        'Unable to save the file %s: %s.' % (fileName, self.outFile.errorString())) 
      self.outFile = None 
      return 

     mode = QHttp.ConnectionModeHttp 
     port = url.port() 
     if port == -1: 
      port = 0 
     self.http.setHost(url.host(), mode, port) 
     self.httpRequestAborted = False 

     path = QUrl.toPercentEncoding(url.path(), "!$&'()*+,;=:@/") 
     if path: 
      path = str(path) 
     else: 
      path = '/' 

     # Download the file. 
     self.httpGetId = self.http.get(path, self.outFile) 

    def cancelDownload(self): 
     self.statusLabel.setText("Download canceled.") 
     self.httpRequestAborted = True 
     self.http.abort() 
     self.close() 

    def httpRequestFinished(self, requestId, error): 
     if requestId != self.httpGetId: 
      return 

     if self.httpRequestAborted: 
      if self.outFile is not None: 
       self.outFile.close() 
       self.outFile.remove() 
       self.outFile = None 
      return 

     self.outFile.close() 

     if error: 
      self.outFile.remove() 
      QMessageBox.information(self, 'Error', 
        'Download failed: %s.' % self.http.errorString()) 

     self.statusLabel.setText('Done')  

    def readResponseHeader(self, responseHeader): 
     # Check for genuine error conditions. 
     if responseHeader.statusCode() not in (200, 300, 301, 302, 303, 307): 
      QMessageBox.information(self, 'Error', 
        'Download failed: %s.' % responseHeader.reasonPhrase()) 
      self.httpRequestAborted = True 
      self.http.abort() 

    def updateDataReadProgress(self, bytesRead, totalBytes): 
     if self.httpRequestAborted: 
      return 
     self.progressBar.setMaximum(totalBytes) 
     self.progressBar.setValue(bytesRead) 

if __name__ == '__main__': 
    import sys 
    app = QApplication(sys.argv) 
    downloader = Downloader() 
    downloader.show() 
    sys.exit(app.exec_()) 
+0

안녕하세요 고맙습니다 .... 제가 전체 다운로드 과정에서 동일한 진행률 표시 줄을 어떻게 사용할 수 있습니까? 일괄 다운로드를 원한다고 말하면서 도와 주시겠습니까? –

+0

죄송합니다,이 코멘트를 놓쳤습니다. 나는이 방법이 파일과 파일의 크기에 달려 있다고 말한다. 크기가 작고 많은 경우 진행률 막대의 최대 값을 파일 개수로 가져 와서 파일을 다운로드 할 때 함께 이동합니다. 파일 크기가 다른 경우보다 정확한 표시를 위해 다운로드하기 전에 모든 파일의 전체 크기를 가져 와서 진행 막대를 설정해야합니다. –