python - 如何在另一个任务旁边运行 tkinter 的 after event?
问题描述
我正在尝试为执行某些任务的脚本创建一个 tkinter GUI。通过单击开始按钮触发任务,我想添加一个动态标签,通过显示:“工作”来显示任务“正在进行”。→ “工作……” → “工作……”
我参考了这篇文章并编写了以下脚本。在这里,我使用进度条来表示我的“任务”,并期望状态标签在进度条更新时发生变化(如上所述)。
import tkinter as tk
class UI:
def __init__(self):
self.root = tk.Tk()
self.root.title('Hello World')
self.prog_Label = tk.Label(self.root, text='Progress')
self.prog_Label.grid(row=0, column=0, sticky=tk.W, padx=20, pady=(10, 0))
self.prog_Bar = tk.ttk.Progressbar(self.root)
self.prog_Bar.configure(value=0, mode='determinate', orient='horizontal')
self.prog_Bar.grid(row=1, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), padx=20, pady=5)
self.exe_Btn = tk.Button(self.root, text='Start', padx=15, command=self.run, relief='groove')
self.exe_Btn.grid(row=2, column=0, padx=80, pady=(40, 20), sticky=tk.E)
self.prog_Label = tk.Label(self.root, text='Status:-')
self.prog_Label.grid(row=3, column=0, sticky=tk.W, padx=20, pady=10)
self.root.mainloop()
def run(self):
self.update_status('Working')
n = 0
self.prog_Bar.configure(value=n, maximum=100000, mode='determinate', orient='horizontal')
for i in range(100000):
n += 1
self.prog_Bar.configure(value=n)
self.prog_Bar.update_idletasks()
def update_status(self, status=None):
if status is not None:
current_status = 'Status: ' + status
else:
current_status = self.prog_Label['text']
if current_status.endswith('...'):
current_status = current_status.replace('...', '')
else:
current_status += '.'
self.prog_Label['text'] = current_status
self.prog_Label.update_idletasks()
self._status = self.root.after(1000, self.update_status)
if __name__ == '__main__':
ui = UI()
但是,该程序的行为方式是,当单击开始按钮时,虽然状态标签立即从“-”变为“工作中”,但它只是在进度条到达末尾后才开始添加点。
有没有办法修改它以达到我的目的?
解决方案
我稍微改变了你的结构,所以你的任务现在在它自己的类中,而不是睡觉你会在那里执行任务。我为任务添加了一个线程,因为我假设它需要自己的进程,这会阻止应用程序冻结,因为它会阻塞主 UI 循环。
import threading
import time
import tkinter as tk
import tkinter.ttk as ttk
class Task:
def __init__(self):
self.percent_done = 0
threading.Thread(target = self.run).start()
def run(self):
while self.percent_done < 1:
self.percent_done += 0.1
# Do your task here
time.sleep(0.5)
self.percent_done = 1
class Application():
def __init__(self):
self.root = tk.Tk()
self.root.title("Window Title")
self.task = None
self.label_dots = 0
self.prog_bar = tk.ttk.Progressbar(self.root)
self.prog_bar.configure(value=0, maximum=100, mode='determinate', orient='horizontal')
self.prog_bar.grid(row=1, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), padx=20, pady=5)
self.run_btn = tk.Button(self.root, text='Start', padx=15, command=self.start_task, relief='groove')
self.run_btn.grid(row=2, column=0, padx=80, pady=(40, 20), sticky=tk.E)
self.prog_label = tk.Label(self.root, text='Status: -')
self.prog_label.grid(row=3, column=0, sticky=tk.W, padx=20, pady=10)
def start_task(self):
self.task = Task()
self.update_ui()
def update_ui(self):
# Percent is between 0 and 1
if 0 < self.task.percent_done < 1:
status = "Working"
self.label_dots += 1
self.label_dots = self.label_dots % 4
else:
status = "Finished"
self.label_dots = 0
self.prog_bar.configure(value=self.task.percent_done * 100)
label_text = "Status: - " + status + ("." * self.label_dots)
self.prog_label.config(text = label_text)
if status != "Finished":
self.root.after(1000, self.update_ui)
Application().root.mainloop()
推荐阅读
- javascript - 如何在单击按钮时创建叠加层?
- php - 异常级别和日志记录
- python - 如何使用 Python 为 NOWTV 可用电影抓取 HTML
- excel - 根据文本更改计算天数
- java - 如何模拟外部库的对象?
- angular7 - 具有动态数据代码的重复元素在 angular7 中优化
- salt-stack - 如何在目录中执行递归以避免重叠
- html - 在 flex 中设置相等的宽度,但与其他孩子不同
- javascript - 我可以控制 ES6 forEach 循环中的循环数吗
- amazon-web-services - 如何使用私有子网配置 aws codebuild?