|
目录Toplevel控件搭建父子窗口最简明的父子窗口框架改进一:屏蔽和开放按钮改进二:子窗口始终在主窗口之上改进三:增加子窗口的关闭协议改进四:使子窗口长获焦点总结Toplevel控件搭建父子窗口最近,用Python给单位里用的“智慧食堂”系统编制了一个餐卡充值文件生成器,自动匹配餐卡号并快速生成导入数据用的Excel表格,截图如下:使用tkinterToplevel控件弹出子窗口,用作设置备注的子窗口。在编程过程中,边学边写探索到不少新知识,简单介绍如下:最简明的父子窗口框架创建一个主窗口、一个子窗口,各放一个按钮,代码如下:importwin32api,tkinterastkdef_toplevel():top=tk.Toplevel(root)top.title("ToplevelWindow")W,H=400,300top.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}')btn_Close=tk.Button(top,text="Close",command=top.destroy)btn_Close.pack()if__name__=='__main__':#创建主窗口root=tk.Tk()root.title("MainWindow")#获取windows系统桌面分辨率X,Y=win32api.GetSystemMetrics(0),win32api.GetSystemMetrics(1)W,H=600,480root.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}')#创建一个打开Toplevel窗口的按钮btn_Open=tk.Button(root,text="OpenToplevel",command=_toplevel)btn_Open.pack()#运行Tkinter事件循环root.mainloop()上述代码的缺点是主窗口上的Open按钮可以反复点击打开多个子窗口,要想办法按需要来屏蔽它的点击功能。改进一:屏蔽和开放按钮以下代码可以调整按钮的使用状态:tk.DISABLED、tk.NORMALbutton.config(state=tk.DISABLED)button.config(state=tk.NORMAL)打开子窗口时,Open按钮的状态改为tk.DISABLED,此时已无法点击了。importwin32api,tkinterastkclassTopWindow:def__init__(self,parent):top=self.top=tk.Toplevel(parent)top.title("ToplevelWindow")W,H=400,300top.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}')btn_Close=tk.Button(top,text="Close",command=self.on_close)btn_Close.pack()defon_close(self):btn_Open.config(state=tk.NORMAL)self.top.destroy()defon_open():TopWindow(root)btn_Open.config(state=tk.DISABLED)if__name__=='__main__':root=tk.Tk()root.title("MainWindow")X,Y=win32api.GetSystemMetrics(0),win32api.GetSystemMetrics(1)W,H=600,480root.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}')btn_Open=tk.Button(root,text="OpenToplevel",command=on_open)btn_Open.pack()root.mainloop()改进二:子窗口始终在主窗口之上top.transient(root) #设置Toplevel窗口始终在主窗口root的上方importwin32api,tkinterastkclassTopWindow:def__init__(self,parent):top=self.top=tk.Toplevel(parent)top.title("ToplevelWindow")W,H=400,300top.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}')top.transient(root)#设置Toplevel窗口始终在主窗口上方btn_Close=tk.Button(top,text="Close",command=self.on_close)btn_Close.pack()defon_close(self):btn_Open.config(state=tk.NORMAL)self.top.destroy()defon_open():TopWindow(root)btn_Open.config(state=tk.DISABLED)if__name__=='__main__':root=tk.Tk()root.title("MainWindow")X,Y=win32api.GetSystemMetrics(0),win32api.GetSystemMetrics(1)W,H=600,480root.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}')btn_Open=tk.Button(root,text="OpenToplevel",command=on_open)btn_Open.pack()root.mainloop()另外一种方法也能设置子窗口永远在前:top.wm_attributes('-topmost',True) #设置Toplevel窗口在所有窗口的上方两种方法的区别在于后者是全局的设置,它使得子窗口在操作系统中所有窗口的上面,包括其它应用程序的窗口。如下图,请比较一下与上一张截图的效果有啥区别:改进三:增加子窗口的关闭协议如下图,直接点击子窗口右上关闭按钮,只触发窗口默认的top.destroy事件。这样关闭子窗口后,主窗口的按钮状态并不能恢复;以下代码使得子窗口的"WM_DELETE_WINDOW"关闭协议绑定了自定义的关闭事件self.onclose:top.protocol("WM_DELETE_WINDOW",self.on_close)完整代码如下:importwin32api,tkinterastkclassTopWindow:def__init__(self,parent):top=self.top=tk.Toplevel(parent)top.title("ToplevelWindow")W,H=400,300top.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}')top.transient(root)top.protocol("WM_DELETE_WINDOW",self.on_close)btn_Close=tk.Button(top,text="Close",command=self.on_close)btn_Close.pack()defon_close(self):btn_Open.config(state=tk.NORMAL)self.top.destroy()defon_open():TopWindow(root)btn_Open.config(state=tk.DISABLED)if__name__=='__main__':root=tk.Tk()root.title("MainWindow")X,Y=win32api.GetSystemMetrics(0),win32api.GetSystemMetrics(1)W,H=600,480root.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}')btn_Open=tk.Button(root,text="OpenToplevel",command=on_open)btn_Open.pack()root.mainloop()改进四:使子窗口长获焦点top.grab_set() #确保Toplevel窗口长获焦点使用这个方法,前面提到的按钮状态的切换以及子窗口绑定关闭协议的代码都不需要了,非常简洁。top.grab_set()配合 top.transient(root)共同使用(如下标注红色部分),效果最佳:importwin32api,tkinterastk classTopWindow: def__init__(self,parent): top=self.top=tk.Toplevel(parent) top.title("ToplevelWindow") W,H=400,300 top.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}') top.grab_set() top.transient(root) btn_Close=tk.Button(top,text="Close",command=top.destroy) btn_Close.pack()defon_open(): TopWindow(root)if__name__=='__main__': root=tk.Tk() root.title("MainWindow") X,Y=win32api.GetSystemMetrics(0),win32api.GetSystemMetrics(1) W,H=600,480 root.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}') btn_Open=tk.Button(root,text="OpenToplevel",command=on_open) btn_Open.pack() root.mainloop()源代码复制框如下:importwin32api,tkinterastkclassTopWindow:def__init__(self,parent):top=self.top=tk.Toplevel(parent)top.title("ToplevelWindow")W,H=400,300top.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}')top.grab_set()top.transient(root)btn_Close=tk.Button(top,text="Close",command=top.destroy)btn_Close.pack()defon_open():TopWindow(root)if__name__=='__main__':root=tk.Tk()root.title("MainWindow")X,Y=win32api.GetSystemMetrics(0),win32api.GetSystemMetrics(1)W,H=600,480root.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}')btn_Open=tk.Button(root,text="OpenToplevel",command=on_open)btn_Open.pack()root.mainloop()总结通过对toplevel控件的编程操练,掌握了tkinter子窗口的调用方法,了解了topleve的多种特殊方法、响应事件以及绑定协议。
|
|