我发布这个是因为我自己一直在努力寻找这个问题的明确答案。 . .
在尝试为我的程序创建进度条时,我发现使用 tkinter 很难做到。要在不进入可怕的“主循环”的情况下完成创建进度条,I opted to make a class out of the progress bar using threads .通过大量的试错,我发现由于使用了多线程(tkinter 喜欢在主线程),可以定制的东西不多。以下是我尝试过的两个选项,然后是最适合我需要的第三个选项:
方案一:使用回调函数
给定以下代码:
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)
防止窗口被关闭。但是,如果退出或 [ 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)
清除所有 tkinters 窗口选项。然而,进度条不仅在一个奇怪的位置,而且还遮挡了用户窗口。进度条应该对用户友好。
选项 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)
防止用户与窗口进行任何交互。这最适合我对该程序的需求,因为它可以防止窗口关闭并且仍然具有漂亮的外观。 (我唯一的小问题是用户不能再最小化进度条或移动它)。
如果有任何更好的解决方案,我很乐意看到它们。希望这对某人有所帮助。
最佳答案
您可以创建一个只使用 pass
什么都不做的函数。
请看下面:
import tkinter as tk
root=tk.Tk()
def close_program():
root.destroy()
def disable_event():
pass
btn = tk.Button(root, text = "Click me to close", command = close_program)
btn.pack()
root.protocol("WM_DELETE_WINDOW", disable_event)
root.mainloop()
您还可以连同 root.overrideredirect(True)
一起删除工具栏,这将阻止用户使用任何工具栏。离开 root.protocol("WM_DELETE_WINDOW", disable_event)
也会阻止使用 ALT + F4
。
import tkinter as tk
root=tk.Tk()
root.geometry("400x400")
root.overrideredirect(True)
def close_program():
root.destroy()
def disable_event():
pass
btn = tk.Button(root, text = "Click me to close", command = close_program)
btn.pack()
root.protocol("WM_DELETE_WINDOW", disable_event)
root.mainloop()
关于python - 在 tkinter 窗口中禁用退出(或 [ X ]),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45467143/