【发布时间】:2021-12-29 19:18:30
【问题描述】:
我有这个图像下载器,它作为新线程和一个包含进度条的弹出窗口工作。下载期间进度条不会更新,但之后(下载器是用请求编写的,gui 应用程序是用 kivy 制作的)。任何想法如何解决这个问题?
下载器: 它被分隔在另一个文件中
class Downloader(threading.Thread):
def __init__(self, url: str, download_monitor):
super(Downloader, self).__init__(daemon=True) # daemon dies when main die
self.url = url
self.download_monitor = download_monitor # url popup
def run(self) -> None:
# Reset
self.download_monitor.reset()
file_name = self.url.split('/')[-1]
# Less RAM usage
with requests.get(self.url, stream=True) as req: # stream=True not to read at once
req.raise_for_status()
with open('temp/'+file_name, 'wb') as file:
chunks = list(enumerate(req.iter_content(chunk_size=8192)))
self.download_monitor.downloading_progress.max = chunks[-1][0] # last element
for progress, chunk in chunks:
self.download_monitor.downloading_progress.value = progress
file.write(chunk)
弹出 .py: 它被分隔在另一个文件中
class UrlPopup(Popup):
url_input = ObjectProperty()
downloading_progress = ObjectProperty()
def __init__(self, **kwargs):
super(UrlPopup, self).__init__(**kwargs)
def download(self):
# https://www.nasa.gov/sites/default/files/thumbnails/image/hubble_ngc2903_potw2143a.jpg.jpg
if self.url_input.text.startswith('https://'): # if it is url address
download(self.url_input.text, self)
def on_dismiss(self):
self.reset()
self.url_input.text = ''
def reset(self):
self.downloading_progress.max = 0
self.downloading_progress.value = 0
弹出.kv: 它被分隔在另一个文件中
<UrlPopup>:
url_input: url_input
downloading_progress: downloading_progress
id: downloader
title: 'URL address'
size_hint: .25, None
height: 157
BoxLayout:
orientation: 'vertical'
size_hint_y: None
height: 64
TextInput:
id: url_input
multiline: False
size_hint_y: None
height: 32
font_size: 16
ProgressBar:
id: downloading_progress
size_hint_y: None
height: 32
BoxLayout:
orientation: 'horizontal'
size_hint_y: None
height: 32
Button:
text: 'Download'
on_press: root.download()
Button:
text: 'Close'
on_press: root.dismiss()
EDIT1 ApuCoder 我按照你写的做了,但下载后进度仍然更新。 还有其他想法吗? 弹出 .py:
class UrlPopup(Popup):
url_input = ObjectProperty()
downloading_progress = ObjectProperty()
progress_value = NumericProperty()
def update_progress(self, dt):
self.progress_value += 1
下载器.py:
with requests.get(self.url, stream=True) as req: # stream=True not to read at once
req.raise_for_status()
with open('temp/'+file_name, 'wb') as file:
chunks = list(enumerate(req.iter_content(chunk_size=8192)))
self.download_monitor.downloading_progress.max = chunks[-1][0] # last element
Clock.schedule_interval(self.download_monitor.update_progress, .1)
for progress, chunk in chunks:
#self.download_monitor.downloading_progress.value = progress
file.write(chunk)
弹出.kv:
ProgressBar:
id: downloading_progress
value: root.progress_value
size_hint_y: None
height: 32
EDIT2 这与类下载器在同一个文件中。我在按下按钮时调用此函数
def download(url: str, download_monitor):
"""Other thread"""
downloader = Downloader(url, download_monitor)
downloader.start()
【问题讨论】:
-
一种方法是,创建一个
NumericProperty,例如“progress_val”,并将其传递给PopUp .kv内的ProgressBar.value。现在安排 (Clock.schedule_interval) 回调并在间隔后(例如,1/10 秒)不断更新此值。 -
@ApuCoder check EDIT1 你有这个想法吗?
-
从你的代码中不清楚,你在哪里开始线程
Downloader。如果您不更新服务内的属性,您将在最后获得更新的值。我认为,在线程等内部更新或在外部安排回调可能会有所帮助。 -
@ApuCoder 现在是否清楚我在哪里开始线程
DownloaderEDIT2?感谢您的帮助
标签: python python-3.x kivy kivy-language python-3.9