Python tkinter 初探Toplevel控件搭建父子窗口

目录

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的多种特殊方法、响应事件以及绑定协议。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/233493.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

k8s集群1.23.0版本部署说明

1.部署 k8s1.23.0版本与1.26.0版本的部署基本差不多,只不过k8s 1.23版本不需要部署cri-docker,所以只需要在1.26.0版本部署的基础上不要cri-docker的部署即可 参考:kubeadm部署k8s 1.26.0版本高可用集群_kubeadm 高可用集群-CSDN博客 搭建…

【DP】198.打家劫舍

题目 法1&#xff1a;DP class Solution {public int rob(int[] nums) {int n nums.length;if (n 1) {return nums[0];}if (n 2) {return Math.max(nums[0], nums[1]);}int pre0 nums[0], pre1 Math.max(nums[0], nums[1]), max 0;for (int i 2; i < n; i) {max M…

行为型设计模式(一)模版方法模式 迭代器模式

模板方法模式 Template 1、什么是模版方法模式 模版方法模式定义了一个算法的骨架&#xff0c;它将其中一些步骤的实现推迟到子类里面&#xff0c;使得子类可以在不改变算法结构的情况下重新定义算法中的某些步骤。 2、为什么使用模版方法模式 封装不变部分&#xff1a;模版…

iManager服务备份

这里写自定义目录标题 超图微服务云套件大版本升级时&#xff0c;有时候会涉及服务的迁移或重新发布&#xff0c;此时需要对服务进行备份&#xff0c;以免重新发布服务出现漏的&#xff0c;便于核对。本文通过fetch实现了服务的备份&#xff0c;备份成果以数组对象形式存储在tx…

Ubuntu环境下SomeIP/CommonAPI环境搭建详细步骤

环境搭建 1.Boost安装 下载Boost源码 &#xff1a; https://www.boost.org/users/download/ 编译安装 首先安装编译所需依赖 sudo apt-get install build-essential g sudo apt-get install installpython-dev autotools-dev sudo apt-get install installlibicu-dev buil…

搭建知识付费平台?明理信息科技为你提供全程解决方案

明理信息科技saas知识付费平台 在当今数字化时代&#xff0c;知识付费已经成为一种趋势&#xff0c;越来越多的人愿意为有价值的知识付费。然而&#xff0c;公共知识付费平台虽然内容丰富&#xff0c;但难以满足个人或企业个性化的需求和品牌打造。同时&#xff0c;开发和维护…

【容器Docker】Docker学习笔记

1、什么是Docker&#xff1a; Docker 将程序和程序运行所依赖的所有环境都打包到镜像里。“build once, run anywhere”Docker 是容器的一种实现。 Windows 下如何安装Docker: 官方安装教程&#xff1a;Install Docker Desktop on Windows | Docker Docs有两种安装套装&…

使用openMVS库,在VS2022中启用c++17标准编译仍然报错

使用openMVS库&#xff0c;在VS2022中启用c17标准编译仍然报错 现象 项目中引用了某些开源库&#xff08;例如openmvs2.1.0&#xff09;&#xff0c;编译时要求启用编译器对c17的支持。 没问题&#xff01;大家都知道在下图所示的位置调整C语言标准&#xff1a; 但是&#…

sqlite3使用中的问题

1、创建自增使用 integer primary key autoincrement 2、注释使用 – 3、创建表时不能同时创建索引&#xff0c;需要create index 4、删除索引使用drop indx 5、在使用soci更新数据库时&#xff0c;数据没有更新&#xff0c;需要使用statement.execute(true) 6、在使用命令查询…

C++常见面试题-进阶部分50题

问题1&#xff1a; 解释C中的模板元编程是什么。 答案&#xff1a; 模板元编程是一种利用C模板来执行编译时计算的技术。它允许程序在编译期间进行复杂的计算&#xff0c;而非运行时。 问题2&#xff1a; C17中的结构化绑定是什么&#xff1f; 答案&#xff1a; 结构化绑定是…

智能优化算法应用:基于类电磁机制算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于类电磁机制算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于类电磁机制算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.类电磁机制算法4.实验参数设定5.算法…

rpc和消息队列区别

RPC 和消息队列都是分布式微服务系统中重要的组件之一&#xff0c;下面我们来简单对比一下两者&#xff1a; 从用途来看&#xff1a;RPC 主要用来解决两个服务的远程通信问题&#xff0c;不需要了解底层网络的通信机制。通过 RPC可以帮助我们调用远程计算机上某个服务的方法&a…

Unity CG内置文件

文档 内置文件 内置文件中的函数 常用宏 变量 CG内置文件位置和作用 位置 Unity安装目录 Editor/Data/CGIncludes中后缀为cginc的文件 作用 类似CG内置函数&#xff0c;提供常用的函数、结构体、变量等&#xff0c;提高开发效率 使用 CG模块中使用 #include “内置文件…

ArcGIS Pro中去除黑边方法汇总

在有些时候&#xff08;比如镶嵌栅格后&#xff09;&#xff0c;我们获取到的影像数据可能会有黑边&#xff0c;这里为大家汇总一下在ArcGIS Pro中去除黑边的方法&#xff0c;希望能对你有所帮助。 数据来源 本教程所使用的数据是从水经微图中下载的影像数据&#xff0c;除了…

vmware离线安装docker-compose

vmware离线安装docker-compose 最近安装docker-compose&#xff0c;发现git取拉取&#xff0c;不是拒绝连接就是报443错误&#xff0c;或者其他错误 最后发现用包直接传上去好用&#xff0c;不用git拉取了 离线安装docker-compose 本文章给的docker-compose离线包&#xff0c;…

C语言学习第二十四天(预处理)

1、预处理符号 C语言设置了一些可以直接使用的预处理符号 __FILE__//进行编译的源文件 __LINE__//文件当前的行号 __DATE__//文件被编译的日期 __TIME__//文件被编译的时间 __STOC__//如果编译器遵循ANSI C 其值是1&#xff0c;否则未定义 一个例子&#xff1a; printf(&…

JNDI注入Log4jFastJson白盒审计不回显处理

目录 0x00 前言 0x01 Maven 仓库及配置 0x02 JNDI 注入简介 0x03 Java-第三方组件-Log4J&JNDI 0x04 Java-第三方组件-FastJson&反射 0x05 白盒审计 - FastJson 0x06 白盒审计 - Log4j 0x07 不回显的处理方法 0x00 前言 希望和各位大佬一起学习&#xff0c;如果…

多线程面试题

文章目录 1. 如何停止正在运行的线程2. 请你谈谈JMM&#xff08;java内存模型&#xff09;3. AQS4. ReentrantLock实现原理5. 死锁怎么检测 1. 如何停止正在运行的线程 设置一个共享变量作为线程退出的标记&#xff0c;当这个标记不满足时while循环&#xff0c;线程一直运行&a…

uniapp图片上传说明

目录 1.文件上传组件 2.单文件上传 3.多文件上传 4.注意点 1.文件上传组件 前端上传组件使用uni-file-picker&#xff0c;可以自行进行下载使用。默认上传到绑定的服务空间&#xff0c;配置属性auto-upload为false关闭自动上传&#xff0c;可以限定上传的是图片还是文件&am…

Databend 开源周报第 124 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 新增对 Delta 和…