【发布时间】:2018-01-10 01:13:57
【问题描述】:
我发布这个是因为我自己一直在努力寻找这个问题的明确答案。 . .
在尝试为我的程序创建进度条时,我发现使用 tkinter 很难做到。要在不遇到可怕的“主循环”的情况下完成创建进度条,I opted to make a class out of the progress bar using threads。通过大量的尝试一个错误,我发现由于使用了多线程(tkinter喜欢在主线程中),可以定制的东西并不多。以下是我尝试过的两种选择,其次是最适合我需要的第三种:
选项 1:使用回调函数
给定以下代码:
import tkinter as tk
import tkinter.ttk as ttk
import threading
class ProgressbarApp(threading.Thread):
def __init__(self, max_value: int):
self.max_value = max_value
self.root = None
self.pb = None
threading.Thread.__init__(self)
self.lock = threading.Lock() # (1)
self.lock.acquire() # (2)
self.start()
# (1) Makes sure progressbar is fully loaded before executing anything
with self.lock:
return
def close(self):
self.root.quit()
def run(self):
self.root = tk.Tk()
self.root.protocol("WM_DELETE_WINDOW", self.__callback)
self.pb = ttk.Progressbar(self.root, orient='horizontal', length=400, mode='determinate')
self.pb['value'] = 0
self.pb['maximum'] = self.max_value
self.pb.pack()
self.lock.release() # (2) Will release lock when finished
self.root.mainloop()
def update(self, value: int):
self.pb['value'] = value
@staticmethod
def __callback():
return
if __name__ == '__main__':
interval = 100000
my_pb = ProgressbarApp(interval)
for i in range(interval):
my_pb.update(i)
my_pb.close()
# Other stuff goes on . . .
在哪里
self.root.protocol("WM_DELETE_WINDOW", self.__callback)
防止窗口被关闭。但是,如果要按住 Exit 或 [ X ] 按钮,进度条将冻结,直到用户释放按钮。 (__callback 函数不断被调用,阻止其他任务完成)。
选项 2:使用 root.overriderdirect(True)
给定以下代码:
import tkinter as tk
import tkinter.ttk as ttk
import threading
class ProgressbarApp(threading.Thread):
def __init__(self, max_value: int):
self.max_value = max_value
self.root = None
self.pb = None
threading.Thread.__init__(self)
self.lock = threading.Lock() # (1)
self.lock.acquire() # (2)
self.start()
# (1) Makes sure progressbar is fully loaded before executing anything
with self.lock:
return
def close(self):
self.root.quit()
def run(self):
self.root = tk.Tk()
self.root.overrideredirect(True)
self.pb = ttk.Progressbar(self.root, orient='horizontal', length=400, mode='determinate')
self.pb['value'] = 0
self.pb['maximum'] = self.max_value
self.pb.pack()
self.lock.release() # (2) Will release lock when finished
self.root.mainloop()
def update(self, value: int):
self.pb['value'] = value
if __name__ == '__main__':
interval = 100000
my_pb = ProgressbarApp(interval)
for i in range(interval):
my_pb.update(i)
my_pb.close()
# Other stuff goes on . . .
在哪里
self.root.overrideredirect(True)
清除所有 tkinter 窗口选项。但是,进度条不仅位于奇怪的位置,而且还遮挡了用户窗口。进度条应该是用户友好的。
选项 3:使用 root.attributes('-disabled', True)
给定以下代码:
import tkinter as tk
import tkinter.ttk as ttk
import threading
class ProgressbarApp(threading.Thread):
def __init__(self, max_value: int):
self.max_value = max_value
self.root = None
self.pb = None
threading.Thread.__init__(self)
self.lock = threading.Lock() # (1)
self.lock.acquire() # (2)
self.start()
# (1) Makes sure progressbar is fully loaded before executing anything
with self.lock:
return
def close(self):
self.root.quit()
def run(self):
self.root = tk.Tk()
self.root.attributes('-disabled', True)
self.pb = ttk.Progressbar(self.root, orient='horizontal', length=400, mode='determinate')
self.pb['value'] = 0
self.pb['maximum'] = self.max_value
self.pb.pack()
self.lock.release() # (2) Will release lock when finished
self.root.mainloop()
def update(self, value: int):
self.pb['value'] = value
if __name__ == '__main__':
interval = 100000
my_pb = ProgressbarApp(interval)
for i in range(interval):
my_pb.update(i)
my_pb.close()
# Other stuff goes on . . .
在哪里
self.root.attributes('-disabled', True)
阻止任何用户与窗口的交互。这最适合我对该程序的需求,因为它可以防止窗口关闭并且仍然具有漂亮的外观。 (我唯一的小问题是用户不能再最小化进度条或移动它)。
如果有任何更好的解决方案,我很乐意看到它们。希望这对某人有所帮助。
【问题讨论】:
-
这看起来不像是个问题。我不明白你在问什么。
标签: python python-3.x tkinter progress-bar exit