如何使用QThread在不冻结GUI(Python3.4,pyQt5)的情况下查看文件下载进度
因此,我尝试在Python3.4.2和PyQt5中制作一个简单的文件下载程序 QThreads似乎是一种方式,但没有在线教程或我可以理解的PyQt5示例。我所能找到的只是C/C++的Qt5参考资料和一堆PyQt4教程,它们不适用于PyQt5和Python3 以下是GUI屏幕截图: 这是我的代码:如何使用QThread在不冻结GUI(Python3.4,pyQt5)的情况下查看文件下载进度,python,multithreading,python-3.x,pyqt,pyqt5,Python,Multithreading,Python 3.x,Pyqt,Pyqt5,因此,我尝试在Python3.4.2和PyQt5中制作一个简单的文件下载程序 QThreads似乎是一种方式,但没有在线教程或我可以理解的PyQt5示例。我所能找到的只是C/C++的Qt5参考资料和一堆PyQt4教程,它们不适用于PyQt5和Python3 以下是GUI屏幕截图: 这是我的代码: #!usr/bin/env python3 from PyQt5.QtCore import * from PyQt5.QtWidgets import * from string import T
#!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
)实时显示下载进度
另外,这个下载程序在我的GitHub上:修复了它,它还没有完成,但是线程工作非常好 我的GitHub上有最新版本,请点击此处:
您有两个选项:使用QThread和使用signals/slot让线程对话;或者使用python线程和队列进行对话。后者的一个例子
#!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_())