python - 如何在 tkinter 中停止嵌套计算并关闭顶层窗口
问题描述
我Toplevel
在 tkinter 脚本中有一个窗口,其中包含两个对应于嵌套循环的进度条。我想在 Toplevel 窗口中添加一个停止按钮来终止执行并关闭 Toplevel 窗口而不是根。
from tkinter import Tk, Toplevel,Button,Label,TOP,BOTH,DoubleVar
from tkinter.ttk import Progressbar
import time
root = Tk()
root.configure(bg='lightgray')
root.wm_title("Main")
progress_window = Toplevel()
progress_window.attributes('-topmost', 'true')
progress_window.configure(bg='lightgrey')
progress_window.wm_title("Progress")
progress_window_label = Label(root, text="")
progress_window.geometry('600x300')
progress_window_label.pack()
M=4 # outer loop
N=5 # inner loop
progress1_var=DoubleVar()
progress1bar=Progressbar(master=progress_window,variable=progress1_var,length=M)
progress1bar.pack(side=TOP,ipady=5,fill=BOTH,expand=True)
progress1_var.set(0)
progress1bar.update()
progress1bar_label=Label(master=progress_window,text='Bar1',bg='lightgray')
progress1bar_label.pack(side=TOP,pady=5,fill=BOTH, expand=True)
progress2_var = DoubleVar()
progress2bar=Progressbar(master=progress_window,variable=progress2_var,length=N)
progress2bar.pack(side=TOP,ipady=5,fill=BOTH, expand=True)
progress2_var.set(0)
progress2bar.update()
progress2bar_label=Label(master=progress_window,text='Bar2',bg='lightgray')
progress2bar_label.pack(side=TOP,pady=5,fill=BOTH, expand=True)
def _stop():
return
stop_button=Button(master=progress_window, text="Cancel",command=_stop)
stop_button.pack(side=TOP,pady=5,fill=BOTH, expand=True)
for t in range(M):
progress1_var.set(t/M)
progress1bar_label.config(text='Bar 1: '+str(round((t+1)/M*100,3))+'%')
progress1bar.update()
progress2_var.set(0)
progress2bar.update()
for i in range(N):
progress2_var.set(i/N)
time.sleep(1.0) #Sleep to slow down execution and view progress window
progress2bar_label.config(text='Bar 2: '+str(round((i+1)/N*100,3))+'%')
progress2bar.update()
progress_window.destroy()
root.mainloop()
停止按钮出现在应该但不起作用的位置并停止执行。这必须是一个非常基本的错误,但我不知道如何纠正它。
解决方案
我做了一些修改,主要是添加了protocol
forroot
和progress_window
.
我还创建了一个名为killed
用于中断for
循环的标志。我已将它们放在一个由after
.
这阻止了TclError: Invalid command name .!toplevel.!label2
from tkinter import Tk, Toplevel, Button, Label, TOP, BOTH, DoubleVar
from tkinter.ttk import Progressbar
import time
killed = False
root = Tk()
root.configure(bg = 'lightgray')
root.wm_title("Main")
root.update()
progress_window = Toplevel()
def stop():
global killed
killed = True
progress_window.destroy()
root.destroy()
# Added protocol controls for exit
root.protocol( "WM_DELETE_WINDOW", stop )
progress_window.protocol( "WM_DELETE_WINDOW", stop )
progress_window.attributes('-topmost', 'true')
progress_window.configure(bg = 'lightgrey')
progress_window.wm_title("Progress")
progress_window_label = Label(root, text = "")
progress_window.geometry('600x300')
progress_window_label.pack()
M = 4 # outer loop
N = 5 # inner loop
progress1_var = DoubleVar()
progress1bar = Progressbar(master = progress_window, variable = progress1_var, length = M)
progress1bar.pack(side = TOP, ipady = 5, fill = BOTH, expand = True)
progress1_var.set(0)
progress1bar.update()
progress1bar_label = Label(master = progress_window, text = 'Bar1', bg = 'lightgray')
progress1bar_label.pack(side = TOP, pady = 5, fill = BOTH, expand = True)
progress2_var = DoubleVar()
progress2bar = Progressbar(master = progress_window, variable = progress2_var, length = N)
progress2bar.pack(side = TOP, ipady = 5, fill = BOTH, expand = True)
progress2_var.set(0)
progress2bar.update()
progress2bar_label = Label(master = progress_window, text = 'Bar2', bg = 'lightgray')
progress2bar_label.pack(side = TOP, pady = 5, fill = BOTH, expand = True)
def process():
for t in range(M):
if killed:
break
progress1_var.set(t/M)
progress1bar_label.config(text = "Bar 1: " + str( round( (t+1)/M*100, 3)) + "%")
progress1bar.update()
progress2_var.set(0)
progress2bar.update()
for i in range(N):
progress2_var.set(i/N)
time.sleep(1.0)
if killed:
break
progress2bar_label.config(text = "Bar 2: " + str( round( (i+1)/N*100, 3)) + "%")
progress2bar.update()
stop_button = Button(master = progress_window, text = "Cancel", command = stop)
stop_button.pack(side = TOP, pady = 5, fill = BOTH, expand = True)
root.after( 1000, process )
root.mainloop()
推荐阅读
- python - 我得到 a += b 的 TypeError,但不是 b += a (numpy)
- java - Android Studio - 如何从手机号码获取用户详细信息?
- google-assistant-sdk - 移动应用程序中的 Google 助理自定义命令
- android - Unity Camera 无法在 Android 上显示整个游戏屏幕(画布)
- ios - 登录屏幕后显示侧面菜单
- pandas - 如何使用逗号分隔值删除重复项和 dcast pandas 数据帧
- php - PHP 类对象作为其他类参数
- python - 将颜色条作为图例添加到 matplotlib 散点图(多个子图、多个散点图)
- wordpress - 如何在二十六主题的商店页面中添加过滤器
- jquery - 获取 contentEditable div 的第一行