目录
Toplevel控件搭建父子窗口
最扼要的父子窗口框架
改良一:屏蔽和开明按钮
改良二:子窗口一直在主窗口之上
改良三:参与子窗口的封锁协定
改良四:使子窗口长获焦点
总结
Toplevel控件搭建父子窗口
最近,用Python给单位里用的“智慧食堂”系统编制了一个餐卡充值文件生成器,智能婚配餐卡号并极速生成导入数据用的Excel表格,截图如下:
经常使用tkinter Toplevel控件弹出子窗口,用作设置备注的子窗口。在编程环节中,边学边写探求到不少新常识,繁难引见如下:
最扼要的父子窗口框架
创立一个主窗口、一个子窗口,各放一个按钮,代码如下:
import win32api, tkinter as tkdef _toplevel():top = tk.Toplevel(root)top.title("Toplevel Window")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("Main Window")# 失掉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="Open Toplevel", command=_toplevel)btn_Open.pack()# 运转Tkinter事情循环root.mainloop()
上述代码的缺陷是主窗口上的Open按钮可以重复点击关上多个子窗口,要想方法按须要来屏蔽它的点击配置。
改良一:屏蔽和开明按钮
以下代码可以调整按钮的经常使用形态:tk.DISABLED、tk.NORMAL
button.config(state=tk.DISABLED)
button.config(state=tk.NORMAL)
关上子窗口时,Open按钮的形态改为tk.DISABLED,此时已不可点击了。
import win32api, tkinter as tk class TopWindow:def __init__(self, parent): top = self.top = tk.Toplevel(parent)top.title("Toplevel Window")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()def on_close(self):btn_Open.config(state=tk.NORMAL)self.top.destroy()def on_open():TopWindow(root)btn_Open.config(state=tk.DISABLED)if __name__=='__main__': root = tk.Tk() root.title("Main Window") 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="Open Toplevel", command=on_open)btn_Open.pack()root.mainloop()
改良二:子窗口一直在主窗口之上
top.transient(root) # 设置Toplevel窗口一直在主窗口root的上方
import win32api, tkinter as tk class TopWindow:def __init__(self, parent): top = self.top = tk.Toplevel(parent)top.title("Toplevel Window")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()def on_close(self):btn_Open.config(state=tk.NORMAL)self.top.destroy()def on_open():TopWindow(root)btn_Open.config(state=tk.DISABLED)if __name__=='__main__': root = tk.Tk() root.title("Main Window") 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="Open Toplevel", 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)
完整代码如下:
import win32api, tkinter as tk class TopWindow:def __init__(self, parent): top = self.top = tk.Toplevel(parent)top.title("Toplevel Window")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()def on_close(self):btn_Open.config(state=tk.NORMAL)self.top.destroy()def on_open():TopWindow(root)btn_Open.config(state=tk.DISABLED)if __name__=='__main__': root = tk.Tk() root.title("Main Window") 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="Open Toplevel", command=on_open)btn_Open.pack()root.mainloop()
改良四:使子窗口长获焦点
top.grab_set() # 确保Toplevel窗口长获焦点
经常使用这个方法,前面提到的按钮形态的切换以及子窗口绑定封锁协定的代码都不须要了,十分繁复。top.grab_set() 配合 top.transient(root) 独特经常使用(如下标注白色局部),成果最佳:
import win32api, tkinter as tk
class TopWindow:
def __init__(self, parent):
top = self.top = tk.Toplevel(parent)
top.title("Toplevel Window")
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()
def on_open():
TopWindow(root)
if __name__=='__main__':
root = tk.Tk()
root.title("Main Window")
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="Open Toplevel", command=on_open)
btn_Open.pack()
root.mainloop()
源代码复制框如下:
import win32api, tkinter as tk class TopWindow:def __init__(self, parent): top = self.top = tk.Toplevel(parent)top.title("Toplevel Window")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()def on_open():TopWindow(root)if __name__=='__main__': root = tk.Tk() root.title("Main Window") 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="Open Toplevel", command=on_open)btn_Open.pack()root.mainloop()
总结
经过对toplevel控件的编程操练,把握了tkinter子窗口的调用方法,了解了topleve的多种不凡方法、照应事情以及绑定协定。
还没有评论,来说两句吧...