【问题标题】:How to see a file download progress without the GUI freezing (python 3.4, pyQt5) using QThread如何使用 QThread 在不冻结 GUI(python 3.4,pyQt5)的情况下查看文件下载进度
【发布时间】:2014-12-18 16:44:19
【问题描述】:

所以我正在尝试在 Python 3.4.2 和 PyQt5 中制作一个简单的文件下载器

QThreads 似乎是这样,但没有在线教程或我可以理解的 PyQt5 示例。我能找到的只是 C/C++ 的 Qt5 参考和一堆不适用于 PyQt5 和 Python 3 的 PyQt4 教程

这是 GUI 屏幕截图:http://i.imgur.com/KGjqRRK.png

这是我的代码:

#!usr/bin/env python3

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

from string import Template
import urllib.request
import sys


class Form(QWidget):
    def __init__(self, parent=None):
        super(Form, self).__init__(parent)

        lblUrl= QLabel("File URL:")
        self.txtURL = QLineEdit()
        self.bttDL = QPushButton("&Download")
        self.pbar = QProgressBar()
        self.pbar.setMinimum(0)

        buttonLayout1 = QVBoxLayout()
        buttonLayout1.addWidget(lblUrl)
        buttonLayout1.addWidget(self.txtURL)
        buttonLayout1.addWidget(self.bttDL)
        buttonLayout1.addWidget(self.pbar)

        self.bttDL.clicked.connect(self.bttPush)

        mainLayout = QGridLayout()
        mainLayout.addLayout(buttonLayout1, 0, 1)

        self.setLayout(mainLayout)
        self.setWindowTitle("pySFD")

    def bttPush(self):
        # check if the download is already running or just disable the button
        # while it's running
        url = self.txtURL.text()
        if url == "":
            QMessageBox.information(self, "Empty URL",
                    "Please enter the URL of the file you want to download.")
            return
        else:
            filename = str(QFileDialog.getSaveFileName(self, 'Choose the download location and file name', '.'))
            filename = filename[:-6]
            filename = filename.split("('",maxsplit=1)[1]

        self.dlThread = downloaderThread()
        self.dlThread.connect(dlThread.run)
        self.dlThread.start()
        self.dlThread.emit(url)

class downloaderThread(QThread):
    def __init__(self):
        QThread.__init__(self)

    def __del__(self):
        self.wait()

    def run(self, dlLink):
            while dlLink.length == 0:
                QThread.sleep(1)
                pass
            def report(block_count, block_size, total_size):
                if block_count == 0:
                    self.pbar.setValue(0)
                if (block_count * block_size) == total_size:
                    QMessageBox.information(self,"Done!","Download finished!")
                    return
                self.pbar.setValue(self.pbar.value() + block_size)

            urllib.request.urlretrieve(dlLink, filename, reporthook=report)
            self.terminate()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    screen = Form()
    screen.show()
    sys.exit(app.exec_())

我尝试了很多方法,但似乎都不起作用。

如何让进度条(self.pbar)实时显示下载进度?

PS。这个下载器在我的 GitHub 上:https://github.com/dKatara/pySFD

【问题讨论】:

标签: python multithreading python-3.x pyqt pyqt5


【解决方案1】:

已修复,尚未完成,但线程效果很好!

最新版本在我的 GitHub 上:https://github.com/dKatara/pySFD

#!usr/bin/env python3

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

import urllib.request
import sys
import threading


dlThread = 0
hWindow = 0
fProgressCounter = 0.0

class Form(QWidget):
    def __init__(self, parent=None):
        super(Form, self).__init__(parent)

        global hWindow
        hWindow = self

        lblUrl = QLabel("File URL:")
        self.txtURL = QLineEdit()
        self.bttDL = QPushButton("&Download")
        self.pbar = QProgressBar()

        self.pbar.setMinimum(0)
        self.pbar.setMaximum(100)

        buttonLayout1 = QVBoxLayout()
        buttonLayout1.addWidget(lblUrl)
        buttonLayout1.addWidget(self.txtURL)
        buttonLayout1.addWidget(self.bttDL)
        buttonLayout1.addWidget(self.pbar)

        self.bttDL.clicked.connect(self.bttPush)

        mainLayout = QGridLayout()
        mainLayout.addLayout(buttonLayout1, 0, 1)

        self.setLayout(mainLayout)
        self.setWindowTitle("pySFD")
    def bttPush(self):
        global dlThread

        hSignals = sigHandling()
        hSignals.dlProgress_update.connect(hSignals.pbar_incrementer)
        hSignals.dlProgress_done.connect(hSignals.dlDone)

        url = self.txtURL.text()
        if url == "":
            QMessageBox.information(self, "Empty URL",
                    "Please enter the URL of the file you want to download.")
            return
        else:
            filename = str(QFileDialog.getSaveFileName(self, 'Choose the download location and file name', '.')) ## DETECT A CANCEL
            filename = filename[:-6]
            filename = filename.split("('",maxsplit=1)[1]

        self.bttDL.setEnabled(False)
        dlThread = threading.Thread(target=hSignals.runDL,args=(url, filename))
        dlThread.start()
        return

    def pbarIncValue(self, val):
        global fProgressCounter
        #print("pbarIncValue({0})\nfProgressCounter={1}".format(val,fProgressCounter))

        if self.pbar.value() >= 100:
            self.dlProgress_done.emit()
            return
        if fProgressCounter > 1.0: # FIX
            self.pbar.setValue(self.pbar.value() + 1)
            fProgressCounter -= 1.0
            fProgressCounter += val
        else:
            fProgressCounter += val

class sigHandling(QObject):
    dlProgress_update = pyqtSignal(float)
    dlProgress_done = pyqtSignal()

    @pyqtSlot(float)
    def pbar_incrementer(self, val):
        hWindow.pbarIncValue(val)

    @pyqtSlot()
    def dlDone(self):
        print("in dlDone")
        hWindow.pbar.setValue(100)
        hWindow.bttDL.setEnabled(True)

    def runDL(self, dlLink, filename):
        #print("in run")
        global dlThread, hWindow
        def report(block_count, block_size, total_size):
            if block_count == 0:
                #print("block_count == 0")
                self.dlProgress_update.emit(0)
            if (block_count * block_size) == total_size:
                self.dlProgress_done.emit()
            incAmount = float((100*block_size) / total_size)
            #print("BS={0} TS={1} incAmount={2}".format(block_size,total_size,incAmount))
            self.dlProgress_update.emit(incAmount)

        urllib.request.urlretrieve(dlLink, filename, reporthook=report)
        #print("emit dlProgress_done")
        self.dlProgress_done.emit()
        #print("about to leave dlThread")
        pass

if __name__ == '__main__':
    app = QApplication(sys.argv)
    screen = Form()
    screen.show()
    sys.exit(app.exec_())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-08
    • 2022-01-05
    • 2018-11-08
    • 2017-05-22
    • 1970-01-01
    • 2022-11-16
    • 1970-01-01
    相关资源
    最近更新 更多