从另一个运行 FTP 下载的线程更新 PyQt 进度
问题描述
我想从另一个类/线程访问进度条(在 Ui_MainWindow()
类中)setMaximum()
(DownloadThread()代码>类).
I want to access progress bar's (which is in the Ui_MainWindow()
class) setMaximum()
from another class/thread (DownloadThread()
class).
我尝试让 DownloadThread()
类继承自 Ui_MainWindow
:DownloadThread(Ui_MainWindow)
.但是当我尝试设置最大进度条值时:
I tried making DownloadThread()
class inherit from Ui_MainWindow
:
DownloadThread(Ui_MainWindow)
. But when I try to set the maximum progress bar value:
Ui_MainWindow.progressBar.setMaximum(100)
我收到此错误:
AttributeError:类型对象Ui_MainWindow"没有属性progressBar"
AttributeError: type object 'Ui_MainWindow' has no attribute 'progressBar'
我的代码:
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
# ...
self.updateButton = QtGui.QPushButton(self.centralwidget)
self.progressBar = QtGui.QProgressBar(self.centralwidget)
self.updateStatusText = QtGui.QLabel(self.centralwidget)
# ...
self.updateButton.clicked.connect(self.download_file)
# ...
def download_file(self):
self.thread = DownloadThread()
self.thread.data_downloaded.connect(self.on_data_ready)
self.thread.start()
def on_data_ready(self, data):
self.updateStatusText.setText(str(data))
class DownloadThread(QtCore.QThread, Ui_MainWindow):
data_downloaded = QtCore.pyqtSignal(object)
def run(self):
self.data_downloaded.emit('Status: Connecting...')
ftp = FTP('example.com')
ftp.login(user='user', passwd='pass')
ftp.cwd('/some_directory/')
filename = '100MB.bin'
totalsize = ftp.size(filename)
print(totalsize)
# SET THE MAXIMUM VALUE OF THE PROGRESS BAR
Ui_MainWindow.progressBar.setMaximum(totalsize)
self.data_downloaded.emit('Status: Downloading...')
global localfile
with open(filename, 'wb') as localfile:
ftp.retrbinary('RETR ' + filename, self.file_write)
ftp.quit()
localfile.close()
self.data_downloaded.emit('Status: Updated!')
def file_write(self, data):
global localfile
localfile.write(data)
print(len(data))
解决方案
直接的问题是 Ui_MainWindow
是一个类,而不是类的实例.您必须将窗口"self
传递给 DownloadThread
.但这无论如何都不是正确的解决方案.您不能从另一个线程访问 PyQt 小部件.相反,使用您已经使用的相同技术来更新状态文本(FTP 下载,带有显示当前状态的文本标签下载).
The immediate problem is that Ui_MainWindow
is a class, not an instance of the class. You would have to pass your "window" self
to the DownloadThread
. But that's not the right solution anyway. You cannot access PyQt widgets from another thread. Instead, use the same technique as you already do, to update the status text (FTP download with text label showing the current status of the download).
class Ui_MainWindow(object):
def download_file(self):
self.thread = DownloadThread()
self.thread.data_downloaded.connect(self.on_data_ready)
self.thread.data_progress.connect(self.on_progress_ready)
self.progress_initialized = False
self.thread.start()
def on_progress_ready(self, data):
# The first signal sets the maximum, the other signals increase a progress
if self.progress_initialized:
self.progressBar.setValue(self.progressBar.value() + int(data))
else:
self.progressBar.setMaximum(int(data))
self.progress_initialized = True
class DownloadThread(QtCore.QThread):
data_downloaded = QtCore.pyqtSignal(object)
data_progress = QtCore.pyqtSignal(object)
def run(self):
self.data_downloaded.emit('Status: Connecting...')
with FTP('example.com') as ftp:
ftp.login(user='user', passwd='pass')
ftp.cwd('/some_directory/')
filename = '100MB.bin'
totalsize = ftp.size(filename)
print(totalsize)
# The first signal sets the maximum
self.data_progress.emit(str(totalsize))
self.data_downloaded.emit('Status: Downloading...')
with open(filename, 'wb') as self.localfile:
ftp.retrbinary('RETR ' + filename, self.file_write)
self.data_downloaded.emit('Status: Updated!')
def file_write(self, data):
self.localfile.write(data)
# The other signals increase a progress
self.data_progress.emit(str(len(data)))
对代码的其他更改:
global localfile
是一种不好的做法.请改用self.localfile
.- 不需要
localfile.close()
,with
可以解决这个问题. - 类似地,
ftp.quit()
应该替换为with
. DownloadThread
无需从Ui_MainWindow
继承.
global localfile
is a bad practice. Useself.localfile
instead.- There's no need for
localfile.close()
,with
takes care of that. - Similarly
ftp.quit()
should be replaced withwith
. - There's no need for
DownloadThread
to inherit fromUi_MainWindow
.
相关文章