首页 > Python资料 博客日记
Python tkinter 初探Toplevel控件搭建父子窗口
2024-03-06 06:00:07Python资料围观170次
目录
Toplevel控件搭建父子窗口
最近,用Python给单位里用的“智慧食堂”系统编制了一个餐卡充值文件生成器,自动匹配餐卡号并快速生成导入数据用的Excel表格,截图如下:
使用tkinter Toplevel控件弹出子窗口,用作设置备注的子窗口。在编程过程中,边学边写探索到不少新知识,简单介绍如下:
最简明的父子窗口框架
创建一个主窗口、一个子窗口,各放一个按钮,代码如下:
import win32api, tkinter as tk
def _toplevel():
top = tk.Toplevel(root)
top.title("Toplevel Window")
W,H=400,300
top.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,480
root.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,300
top.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,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()
改进二:子窗口始终在主窗口之上
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,300
top.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,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()
另外一种方法也能设置子窗口永远在前:
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,300
top.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,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()
改进四:使子窗口长获焦点
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,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()
总结
通过对toplevel控件的编程操练,掌握了tkinter子窗口的调用方法,了解了topleve的多种特殊方法、响应事件以及绑定协议。
标签:
相关文章
最新发布
- 华为OD机试E卷 --流浪地球--24年OD统一考试(Java & JS & Python & C & C++)
- Python 3.7-3.11版本dlib库快速安装指南
- python 更换pip源
- 华为OD机试E卷 --恢复数字序列--24年OD统一考试(Java & JS & Python & C & C++)
- 华为OD机试E卷 --选修课--24年OD统一考试(Java & JS & Python & C & C++)
- python SQLAlchemy ORM——从零开始学习 01 安装库
- Python 入门教程(2)搭建环境 | 2.3、VSCode配置Python开发环境
- Django 3 Web应用开发实战PDF、EPUB免费下载
- Python的元组和字典知识点(超详细教学)
- 小波变换算法详解(附Python和C++代码)
点击排行
- 版本匹配指南:Numpy版本和Python版本的对应关系
- 版本匹配指南:PyTorch版本、torchvision 版本和Python版本的对应关系
- Python 可视化 web 神器:streamlit、Gradio、dash、nicegui;低代码 Python Web 框架:PyWebIO
- 相关性分析——Pearson相关系数+热力图(附data和Python完整代码)
- Anaconda版本和Python版本对应关系(持续更新...)
- Python与PyTorch的版本对应
- Windows上安装 Python 环境并配置环境变量 (超详细教程)
- Python pyinstaller打包exe最完整教程