[英]Python Tkinter - closing a child window with an exit button
我有一个带有Piface转接板的Raspberry Pi。 我制作了一个GUI,用于控制Piface板上的LED。 GUI上的一个按钮可打开一个新窗口,按下该按钮可启动和停止运行一小段代码,以使LED连续地上下运行,例如Knight Riders车,并在线程中使用While循环。 在这个新窗口中,我添加了一个退出按钮。 我想添加一段代码,当我单击“退出”按钮,然后返回主窗口时,它将关闭新窗口。 我看了很多例子,但是根本看不到我应该放在哪里。 我尝试过“退出”,但它关闭了整个程序。 看完许多示例后,我也许会以不太正确的方式创建新窗口,因此随时告诉我是否有更好的方法。
那么有没有更好的方法呢? 任何指针将不胜感激。
提前致谢。
这是一段代码。
def new_window(self):
print('New Window')
self.newWindow = tk.Toplevel(self.master)
self.app = App2(self.newWindow)
self.newWindow.grab_set() # I added this line to stop opening multiple new windows
class App2:
def __init__(self, master):
frame = Frame(master)
frame.pack()
Label(frame, text='Turn LED ON').grid(row=0, column=0)
Label(frame, text='Turn LED OFF').grid(row=0, column=1)
self.button0 = Button(frame, text='Knight Rider OFF', command=self.convert0)
self.button0.grid(row=2, column=0)
self.LED0 = Label(frame, image=logo2)
self.LED0.grid(row=2, column=1)
self.button9 = Button(frame, text='Exit', command=self.close_window)
self.button9.grid(row=3, column=0)
def convert0(self, tog=[0]):
tog[0] = not tog[0]
if tog[0]:
print('Knight Rider ON')
self.button0.config(text='Knight Rider ON')
t=threading.Thread(target=self.LED)
t.start()
self.signal = True #added to stop thread
self.LED0.config(image = logo)
else:
print('Knight Rider OFF')
self.button0.config(text='Knight Rider OFF')
self.signal = False #added to stop thread
self.LED0.config(image = logo2)
def LED(self):
while self.signal: #added to stop thread
a=0
while self.signal: #added to stop thread
pfio.digital_write(a,1) #turn on
sleep(0.05)
pfio.digital_write(a,0) #turn off
sleep(0.05)
a=a+1
if a==7:
break
while self.signal: #added to stop thread
pfio.digital_write(a,1) #turn on
sleep(0.05)
pfio.digital_write(a,0) #turn off
sleep(0.05)
a=a-1
if a==0:
break
def close_window(self):
print('Close Child window')
#self.newWindow.destroy() Not sure what to put here?
如果将new_window
放入App2,则应该没问题。
self.newWindow.destroy()
销毁窗口。 这是正确的选择。 然后关闭窗口,并且窗口中的所有小部件也将被销毁。
quit()
将停止mainloop()
在这种情况下,程序将在最后一行结束,并破坏所有内容。
您肯定要使用destroy
。
class App2:
newWindow = None
def close_window(self):
print('Close Child window')
if self.newWindow:
try: self.newWindow.destroy()
except (): pass # fill in the error here
self.newWindow = None
def new_window(self):
print('New Window')
self.close_window()
self.newWindow = tk.Toplevel(self.master)
self.app = App2(self.newWindow)
self.newWindow.grab_set()
@classmethod
def start_app(cls):
window = tk.Tk(self.master)
app = App2(window)
return app
您不应该从线程访问Tkinter。 看看替代品
当我开始使用Tkinter时,我也对quit
和destroy
感到困惑。
在Tk中,使用destroy方法销毁窗口。 因此,如果您有一个对话框顶层并且想要摆脱它,则可以调用其destroy()方法。 或者,您可以撤回该对象,在这种情况下,该对象继续存在,但不再显示在屏幕上,要重新显示它,请在顶层框架中deiconify()。 摧毁它们更普遍。 这是创建和销毁子对话框的简单示例:
import sys
from Tkinter import *
class App(Frame):
def __init__(self, parent = None):
Frame.__init__(self, parent)
self.grid()
self.button = Button(self, text = "Create Dialog", command=self.CreateDialog)
self.button.grid()
def CreateDialog(self):
dialog = Toplevel(self)
dialog.wm_title("Dialog window")
dialog.wm_transient(self)
dialog.wm_protocol("WM_DELETE_WINDOW", lambda: self.onDeleteChild(dialog))
button = Button(dialog, text="Close", command=lambda: self.onDeleteChild(dialog))
button.grid()
def onDeleteChild(self, w):
w.destroy()
def main():
app = App()
app.mainloop()
if __name__ == "__main__":
sys.exit(main())
您还应该考虑在代码中使用计时器来驱动LED循环,而不是while循环。 看看使用Tk的after函数在间隔后运行代码的答案 。 如果在处理程序中调用后重新安排另一个函数,则可以安排一个函数定期运行,并避免阻塞事件处理而无需其他线程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.