我希望有一个主窗口和一个或多个可以按需打开的Toplevel()
窗口。我能够创建窗户,甚至可以销毁它们。
但是,我试图在主窗口中实现一个按钮,它打开和关闭第二个窗口(第二个窗口应该始终是唯一的,即永远不会同时打开两次)。在摆弄一点之后,这就是我现在所拥有的:
#!/usr/bin/python3
import tkinter as tk
from tkinter import ttk
import tkinter.font
class baseApp(ttk.Frame):
def __init__(self,master,*args,**kwargs):
super().__init__(master,*args,**kwargs)
self.master = master
self.mainframe = ttk.Frame(master)
self.topframe = ttk.Frame(self.mainframe, padding="5 8 5 5")
self.topframe.pack(side=tk.TOP, fill=tk.X)
self.mainframe.pack(side=tk.TOP, expand=True, fill=tk.BOTH)
class App(baseApp):
def __init__(self,master,*args,**kwargs):
super().__init__(master,*args,**kwargs)
self.master = master
self.button1 = ttk.Button(self.topframe,text="One",command=self.button_one)
self.btn_remessas = ttk.Button(self.topframe,text="Open/close Toplevel window",command=self.create_window1)
self.button1.grid(row=0,column=0)
self.btn_remessas.grid(row=0,column=1)
self.topframe.pack(side=tk.TOP, fill=tk.X)
self.mainframe.pack(side=tk.TOP, expand=True, fill=tk.BOTH)
def create_window1(self):
if current_state.window2_open == False:
self.newWindow2 = tk.Toplevel(self.master)
self.newWindow2.geometry('600x500+680+0')
self.newWindow2.title('Second window')
self.janela_remessas = SecondWindow(self.newWindow2)
current_state.window2_open = True
else:
self.newWindow2.destroy()
root.update_idletasks()
current_state.window2_open = False
def button_one(self):
print("button 1 pressed")
class SecondWindow:
def __init__(self,master,*args,**kwargs):
#super().__init__(master,*args,**kwargs)
self.mainframe = ttk.Frame(master, padding="5 8 5 5")
self.topframe = ttk.Frame(self.mainframe)
self.button1 = ttk.Button(self.topframe,text="button",command=self.button_function)
self.button1.pack()
self.topframe.pack(side=tk.TOP, fill=tk.X)
self.mainframe.pack(side=tk.TOP, expand=True, fill=tk.BOTH)
def button_function(self, *event):
print("user just pressed button")
def close_window(self, *event): #Please fix me!
current_state.window2_open = False
self.destroy()
class AppStatus:
def __init__(self):
self.window2_open = False
if __name__ == "__main__":
root = tk.Tk()
app = App(root)
current_state = AppStatus()
root.configure(background='grey95')
root.title('Application window')
root.geometry('1000x760+0+0')
root.bind_all("<Mod2-q>", exit)
root.mainloop()
现在,如果用户点击关闭窗口按钮或相应的键盘快捷键,应用程序将不会知道第二个窗口不再存在,所以当我们按下按钮打开/关闭窗口时,没有任何反应。此外,如果我们一直按下打开/关闭按钮,有时按钮不会打开第二个窗口。我做错了什么?
答案 0 :(得分:4)
您想使用顶级窗口小部件的wm_protocol
方法。特别是WM_DELETE_WINDOW
协议。
>>> import tkinter as tk
>>> root = tk.Tk()
>>> dlg = tk.Toplevel(root)
>>> dlg.wm_title("dialog")
''
>>> root.wm_protocol("WM_DELETE_WINDOW", lambda: print("close root"))
''
>>> dlg.wm_protocol("WM_DELETE_WINDOW", lambda: print("close dialog"))
''
>>> root.mainloop()
close dialog
close root
单击窗口框关闭按钮(大红色X)时输出最后一行。当我单击此按钮时,现在不会退出,并且在任一Tk窗口上也会调用Alt-F4
。
Tk documentation还有更多话要说。我发现的python文档似乎相当稀疏。
答案 1 :(得分:0)
按照patthoyts的建议发布完整的工作代码。
#!/usr/bin/python3
import tkinter as tk
from tkinter import ttk
import tkinter.font
class baseApp(ttk.Frame):
def __init__(self,master,*args,**kwargs):
super().__init__(master,*args,**kwargs)
self.master = master
self.mainframe = ttk.Frame(master)
self.topframe = ttk.Frame(self.mainframe, padding="5 8 5 5")
self.topframe.pack(side=tk.TOP, fill=tk.X)
self.mainframe.pack(side=tk.TOP, expand=True, fill=tk.BOTH)
class App(baseApp):
def __init__(self,master,*args,**kwargs):
super().__init__(master,*args,**kwargs)
self.master = master
self.button1 = ttk.Button(self.topframe,text="One",command=self.button_one)
self.btn_remessas = ttk.Button(self.topframe,text="Open/close Toplevel window",command=self.create_window2)
self.button1.grid(row=0,column=0)
self.btn_remessas.grid(row=0,column=1)
self.topframe.pack(side=tk.TOP, fill=tk.X)
self.mainframe.pack(side=tk.TOP, expand=True, fill=tk.BOTH)
def create_window2(self):
if current_state.window2_open == False:
self.newWindow2 = tk.Toplevel(self.master)
self.newWindow2.geometry('600x500+680+0')
self.newWindow2.title('Second window')
self.janela_remessas = SecondWindow(self.newWindow2)
current_state.window2_open = True
self.newWindow2.wm_protocol("WM_DELETE_WINDOW", lambda: self.close_window2())
else:
self.close_window2()
def close_window2(self, *event):
print("closing window")
root.update_idletasks()
current_state.window2_open = False
self.newWindow2.destroy()
def button_one(self):
print("button 1 pressed")
class SecondWindow:
def __init__(self,master,*args,**kwargs):
#super().__init__(master,*args,**kwargs)
self.mainframe = ttk.Frame(master, padding="5 8 5 5")
self.topframe = ttk.Frame(self.mainframe)
self.button1 = ttk.Button(self.topframe,text="button",command=self.button_function)
self.button1.pack()
self.topframe.pack(side=tk.TOP, fill=tk.X)
self.mainframe.pack(side=tk.TOP, expand=True, fill=tk.BOTH)
def button_function(self, *event):
print("user just pressed button")
def close_window(self, *event): #Please fix me!
current_state.window2_open = False
self.destroy()
class AppStatus:
def __init__(self):
self.window2_open = False
if __name__ == "__main__":
root = tk.Tk()
app = App(root)
current_state = AppStatus()
root.configure(background='grey95')
root.title('Application window')
root.geometry('1000x760+0+0')
root.bind_all("<Mod2-q>", exit)
root.mainloop()