工作环境:界面上多个小组件,包含几个需要实时改变状态的组件。此时需要加入一个弹窗,在网上搜到弹窗的一个Demo并学习,得到如下代码:
from tkinter import *
win = Tk()
#设置窗口大小
win.geometry("700x250")
win.title("子窗口")
def open_win():
def clsose_Win():
top.quit()
top.destroy()
#创建用于打开Toplevel窗口的按钮
top= Toplevel(win)
top.geometry("700x250")
top.title("子窗口")
#在Toplevel窗口中创建一个标签
Label(top, text= "Hello World!").pack()
Button(top, text= "关闭", background= "white", foreground= "blue", font= ('Helvetica 13 bold'), command= clsose_Win).pack(pady= 50)
Label(win, text= "单击按钮以打开弹出窗口", font= ('Helvetica 18')).place(relx=.5, rely=.5, anchor= CENTER)
Button(win, text= "点击我", background= "white", foreground= "blue", font= ('Helvetica 13 bold'), command= open_win).pack(pady= 50)
win.mainloop()
此时可以达成如下效果:
随后掌握了该Demo后,运用在实际项目中,发现多了一下关于线程的奇奇怪怪的报错,此时重新回来研究该Demo。为了模拟实际情况的开发,在父窗口加入一些利用线程,实时可变动的动态组件,例如:计时器,此时Demo代码为:
from tkinter import *
from threading import Thread,Timer
import time
win = Tk()
#设置窗口大小
win.geometry("700x250")
win.title("父窗口")
def open_win():
def clsose_Win():
top.quit()
top.destroy()
#创建用于打开Toplevel窗口的按钮
top= Toplevel(win)
top.geometry("700x250")
top.title("子窗口")
#在Toplevel窗口中创建一个标签
Label(top, text= "Hello World!").pack()
Button(top, text= "关闭", background= "white", foreground= "blue", font= ('Helvetica 13 bold'), command= clsose_Win).pack(pady= 50)
top.mainloop()
def start_timer():
global WorkTime
WorkTime=time.time()
TimeTick()
def TimeTick():
Timer(1, TimeTick).start()
update_timer()
def update_timer():
seconds = int(time.time() - WorkTime) # 计算经过的秒数
hh = seconds // 3600 # 计算小时数
mm = (seconds % 3600) // 60 # 计算分钟数
ss = seconds % 60 # 计算秒数
l1.configure(text="{:02d}:{:02d}:{:02d}".format(hh, mm, ss), foreground='red')
l1 = Label(win, text= "", font= ('Helvetica 18'))
l1.pack(side='top')
b1 = Button(win, text= "点击我", background= "white", foreground= "black", font= ('Helvetica 13 bold'), command= open_win).pack(side = "bottom")
b2 = Button(win, text= "计时", background= "white", foreground= "black", font= ('Helvetica 13 bold'), command=lambda:start_timer()).pack(side = "bottom")
win.mainloop()
由此得到效果为:
与此同时,点击生成的新窗口,同时通过点击按钮来关闭子窗口,发现程序立马报错,计时器也随之停止,报错信息为:RuntimeError: main thread is not in main loop
在本人的实际情况,由于该界面不是整个项目的main函数,所以根据该报错信息找了很久也没找到问题所在。
后面了解,这个报错是由于窗口的mainloop退出了,而导致的该报错,随后看到这个关闭按钮内的代码块:
def clsose_Win():
top.quit()
top.destroy()
由于最初,并不了解这两个方法的具体作用,就直接拿来用了,这是作为初学者的大忌。一定了解陌生的方法对应的作用,才能使用。
这下清楚了,这两个方法都是控制窗口关闭的函数,区别是,quit()会导致整个程序的推出,即父窗口:win.mainloop(),被终止,故,l1.config就无法正常执行,才产生的报错。所以这里,我们需要的是安全退出子窗口,则不需要quit函数,将改行注释掉,需求正常通过。。。