简体   繁体   English

在pyqt4中进行线程化

[英]Threading in pyqt4

In my GUI I have to download lots of stuff in between. 在我的GUI中,我必须下载很多东西。 I use urllib to do that. 我使用urllib来做到这一点。 the problem of course then becomes that the GUI freezes up until everything gets downloaded. 当然问题就是GUI会冻结,直到下载完所有内容。

My code is something like following 我的代码类似于以下内容

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

wherein the above function has the downloading code. 其中上述功能具有下载代码。

There is nothing like sending of shared data among this and the process just involves downloading of the data to a location. 没有什么比在这之间发送共享数据更简单,并且该过程仅涉及将数据下载到位置。

What is the simplest way to not freeze up my GUI ? 什么是不冻结GUI的最简单方法? Should i use multiprocessing or QThreads ? 我应该使用multiprocessing还是QThreads

Can anybody point me to some links.... I do not wish it to be very complex so if there is any easier way do it please point it out.... 任何人都可以指向我一些链接....我不希望它是非常复杂的,所以如果有任何更简单的方法,请指出它....

Thanks a lot... 非常感谢...

Here's an example I've just stripped from a project I was working on a couple of months back using the http example from PyQt as a base. 这是一个例子,我刚刚从几个月前使用PyQt的http示例作为基础的项目中删除了。 It'll download SIP from the Riverbank website. 它将从Riverbank网站下载SIP。

It's using QHttp from QtNetwork instead of urllib and the progress bar is connected to its dataReadProgress signal. 它使用来自QtNetwork的QHttp而不是urllib,进度条连接到其dataReadProgress信号。 This should allow you to reliably download a file as well as having a responsive GUI. 这应该允许您可靠地下载文件以及具有响应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_())

I suggest you to use the QNetworkManager instead and monitor the download process. 我建议你改用QNetworkManager并监控下载过程。

See this other question: pyQT QNetworkManager and ProgressBars 请参阅另一个问题: pyQT QNetworkManager和ProgressBars

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM