我发布这个,因为我自己一直在寻找这个问题的明确答案挣扎。 。 。禁用退出(或[X])在tkinter窗口
为了尝试为我的程序创建进度条,我发现使用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(真)
考虑下面的代码:
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)
清除所有的tkinters窗口选项。但是,进度条不仅位于一个奇怪的位置,而且也遮蔽了用户窗口。进度条应该用户友好。
选项3:使用root.attributes( ' - 禁用',真)
鉴于以下代码:
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)
防止与窗口中的任何用户交互。这最适合我这个程序的需求,因为它可以防止窗户关闭,并且仍然具有很好的外观。 (我唯一的小问题是,用户不能再将进度条最小化或移动它)。
如果有更好的解决方案,我很乐意看到它们。希望这有助于某人。
这看起来并不像一个问题。我不明白你在问什么。 –