过去一年左右我一直在使用tkinter(来自python 3.2和3.4),并且从未遇到过小部件毁坏的问题。
我最近更新了我的Tk / Tcl版本(到ActiveTcl 8.5.18)并且还更新了我的操作系统(到MacOS 10.11)。起初似乎没有窗户会破坏,但我发现如果一个进程仍然在运行,那么destroy就会冻结窗口。
以下代码显示此问题:
#! usr/local/bin/python3.4
class kill_test:
def __init__(self,r=None):
import tkinter as tk
if r is None:
r=tk.Tk()
self.r=r
self.forever_flag=False
self.withdraw=False
self.buttons=[
tk.Label(r,text='Set Hold Flag',relief='groove'),
tk.Label(r,text='Destroy Root',relief='groove'),
tk.Label(r,text='Withdraw and Destroy',relief='groove'),
tk.Label(r,text='Destroy Self',relief='groove'),
tk.Label(r,text='Quit Root',relief='groove'),
tk.Label(r,text='Withdraw and Quit',relief='groove'),
tk.Label(r,text='Make Toplevel',relief='groove')
]
def r_destroy(s=self):
print('root.destroy called')
s.r.destroy()
def b_destroy(s=self):
print('button.destroy called')
for b in self.buttons:
if 'Self' in b['text']:
b.destroy()
def r_quit(s=self):
print('root.quit called')
self.r.quit()
def f_flag(s=self):
print('changing loop_flag')
self.forever_flag=(not self.forever_flag)
for b in self.buttons:
if 'Flag' in b['text']:
if self.forever_flag:
b.base_fg='red'
else:
b.base_fg='black'
def w_destroy(s=self):
print('withdrawing and destroying')
self.r.withdraw()
self.r.destroy()
def w_quit(s=self):
print('withdrawing and quitting')
self.r.withdraw()
self.r.quit()
def t_cmd(s=self):
T=tk.Toplevel()
kill_test(T)
self.cmds=[
f_flag,
r_destroy,
w_destroy,
b_destroy,
r_quit,
w_quit,
t_cmd
]
i=0;j=0
for b,cmd in zip(self.buttons[:-1],self.cmds[:-1]):
b.base_fg=b['fg']
b.bind('<Enter>',lambda e:e.widget.config(bg='lightblue',fg='white'))
b.bind('<Button-1>',lambda e:e.widget.config(bg='darkblue'))
b.bind('<ButtonRelease-1>',lambda e,c=cmd:(e.widget.config(bg='lightblue'),c()))
b.bind('<Leave>',lambda e:e.widget.config(bg='white',fg=e.widget.base_fg))
b.grid(row=i,column=j,sticky='ew')
i+=1
if i>2:
i=0
j+=1
b=self.buttons[-1];cmd=self.cmds[-1]
b.base_fg=b['fg']
b.bind('<Enter>',lambda e:e.widget.config(bg='lightblue',fg='white'))
b.bind('<Button-1>',lambda e:e.widget.config(bg='darkblue'))
b.bind('<ButtonRelease-1>',lambda e,c=cmd:(e.widget.config(bg='lightblue'),c()))
b.bind('<Leave>',lambda e:e.widget.config(bg='white',fg=e.widget.base_fg))
b.grid(row=3,column=0,columnspan=2,sticky='ew')
def run(self):
self.r.mainloop()
if __name__=='__main__':
import time
t=kill_test()
t.run()
if t.forever_flag:
time.sleep(10)
从命令行调用,如果没有按“设置保持标记”按钮,则一切都会顺利退出。
另一方面,如果有人按下它,那么试图通过任何机制破坏窗口只是将窗口冻结到位,直到time.sleep退出。
过去,窗户至少会先消失。
如果有人调用'提取和销毁'按钮,则窗口仍然可见但不活动。如果一个人调用“提取和退出”按钮,它就会消失。
最后,顶层窗口会破坏很好(正如预期的那样,考虑到从未调用过循环),无论对它们做了什么。我放入了测试的顶级按钮版本。
有没有人有关于如何恢复旧行为的提示?