Python tkinter Notebook标签添加关闭按钮元素,及左侧添加存储状态提示图标案例,类似Notepad++页面

效果图展示

图片展示
粉色框是当前页面,橙色框是鼠标经过,红色框是按下按钮,灰色按钮是其他页面的效果;
存储标识可以用来识别页面是否存储:例如当前页面已经保存用蓝色,未保存用红色,其他页面已经保存用灰色,未保存用淡红色。

首先导入模块

import tkinter as tk
from tkinter import ttk

定义一个名为CustomNotebook的类,继承自ttk.Notebook

class CustomNotebook(ttk.Notebook):"""定义一个名为CustomNotebook的类,继承自ttk.Notebook"""__initialized = False  # 初始化一个私有变量,用于标记是否已经初始化def __init__(self, *args, **kwargs):# 如果尚未初始化,则调用自定义初始化方法,并设置已初始化标志if not self.__initialized:self.__initialize_custom_style()#CustomNotebook.__initialized = Trueself.__inititialized = True# 设置notebook的样式为"CustomNotebook"kwargs["style"] = "CustomNotebook"# 调用父类的初始化方法ttk.Notebook.__init__(self, *args, **kwargs)self._active = None # 初始化一个私有变量,用于存储当前活动的tab# 绑定鼠标左键按下事件到on_close_press方法self.bind("<ButtonPress-1>", self.on_close_press, True)# 绑定鼠标左键释放事件到on_close_release方法self.bind("<ButtonRelease-1>", self.on_close_release)def on_close_press(self, event):"""当按钮被按下时触发,位于关闭按钮上方"""# 获取鼠标点击位置的元素element = self.identify(event.x, event.y)# 如果元素包含"close",则执行以下操作if "close" in element:# 获取鼠标点击位置的索引值index = self.index("@%d,%d" % (event.x, event.y))# 将按钮状态设置为按下self.state(['pressed'])# 将_active属性设置为点击的索引值self._active = indexdef on_close_release(self, event):""" 当鼠标在关闭按钮上释放时调用此方法。event:  包含鼠标事件信息的对象。"""if not self.instate(['pressed']): # 如果按钮没有按下状态,直接返回returntry:element =  self.identify(event.x, event.y) # 获取鼠标释放位置的元素index = self.index("@%d,%d" % (event.x, event.y)) # 获取元素在列表中的索引if "close" in element and self._active == index: # 如果元素是关闭按钮,并且当前激活的标签页与释放位置的标签页相同self.forget(index)  # 删除该标签页self.event_generate("<<NotebookTabClosed>>") # 生成一个表示标签页关闭的事件except: passself.state(["!pressed"]) # 将按钮状态设置为非按下状态self._active = None # 将当前激活的标签页设置为Nonedef __initialize_custom_style(self):# 创建一个ttk样式对象style = ttk.Style()# 定义四个图片对象,分别表示关闭按钮的不同状态self.images = (# 元素普通状态时图标tk.PhotoImage("img_closenormal", data='''R0lGODdhCwALAIMAAJKSkpeXl5ubm5+fn6CgoKampqqqqq2trbGxsba2tr29vcHBwdnZ2QAAAAAAAAAAACwAAAAACwALAAAIXQAXJEBwwEDBAgUGHEigYOCBhwYMEBCAIAEDBgYQXhwg4ACCiwwKgOQIEeRGjgUKGgBJYABKgyYZuBRAQORFmwwEBBhgE6FNAQAEDCBAtCVHoAcC6AzANAAAAAYCAgA7'''),# 选中的选项卡的关闭图标tk.PhotoImage("img_closeselected", data='''R0lGODdhCwALAIVUAJ9dcptfe6NfcpthfZ5hfJ9ifp5nfaNjda9lc6Rmea1nfqRpe6Fqfq9ofK1ofqxrfrFndbJqeLJufZ9rgKpngaBqgKtpg6tphK5uhKxvia5xhq91iq1xjK1zj692jLFyg7N1hrJ3i7B2jbF4ja51ka94kq97l698mq9+m7B8mbB/nLCDn6aEoayMprCForGMq7KNq7KPrrOXt7WfwP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAACwALAAAIcgBnwFiBwoQJEh0yUGARQ8YLFwRPHLwQwEUMGjQOcsB4YYAKFxhpbMRooYCJFSlCYlTgoAAJFSlMhHTgQEGBDilSqoyggACGEiFFhGxwAINQGiNCgMAIQcADDR48bAjxQUIEBABaGJgwoQKDBQkOCGAREAA7'''),# 鼠标经过时选项卡的关闭图标tk.PhotoImage("img_closeactive", data='''R0lGODdhCwALAIVSAN5IN+lRNeBQP+5bPvtSP+FSQuJXR+VbRu5dQetfRuVbSf9dS/xeTO5iR+hhTOxlTP1wTP1iUP1kUv9lVPxnVv9rVP1pWP9rWv9vXv5/WP54Xf9yYv11YP90ZP99YP94af97bP99bv6BW/6CYv6FYP+BZf6JZv+Eb/6Jav+Oa+eJe/+Bcf+Edf+Hef+KfP+Rd/+WfP+bev+Pgu+Rhv+RhP+ViP+Zjf+hlv+lmv+1rP+/twAAAAAAAAAAAAAAACwAAAAACwALAAAIcwB13KDhgkWIEB8wRJiBIwcOGzRktFjxwUKBGjh27GABYoNGCQZc2NC4owNJkCsIktRYoYKCDywmkizhQYODDSFWrNyRYsSDCSY1wiBJosGCCxpPvIihMcMAAgwoXOBQAoUJERACzAAAoICAAwkaIAigIiAAOw=='''),# 按下关闭按钮时选项卡的关闭图标tk.PhotoImage("img_closepressed", data='''R0lGODdhCwALAIUAAGsiD20jEHIkEHYlEXsnEX4oEogrE4orFIwsFJEtFJUvFZoxFpwwFp4yF6EzF6YzF642GbU3GbY4Grk5Grk6G7s7G7w6G7w8G8A+HcJAHcVDH8ZEH8dEIMhGIMtJIsxKIs1KIpdxZ8eAbtqIcuKdiQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAACwALAAAIcABDABBA4AACBQscNBARIAGDBxAkVKhwoeIABiRIRJhQIeMFDAUeZCTRMWOGCwYgRBhpMgMGBBEqWBipYcOGDAoolBz5wcOGBRdGchjps0FQEhk6eMgIgoODihgycOgAAoQHDiIsYMBwoeYGDhtGBAQAOw=='''),)# 使用element_create方法创建一个名为"close"的元素,类型为"image",图像文件名为"img_closenormal"style.element_create("close", "image", "img_closenormal",# 下面设置各状态图标,激活顺序越往后的越要写在前面,比如按下要先鼠标经过激活,按下就要写在鼠标经过前# 当元素处于激活、按下、未禁用状态时,显示"img_closepressed"图片("active", "pressed", "!disabled", "img_closepressed"),# 当元素处于激活且未禁用状态时,显示"img_closeactive"图片("active", "!disabled", "img_closeactive"), # 当选项卡处于选中状态时,显示"img_closeselected"图片("selected", "img_closeselected"), # 设置元素的边框宽度为10像素,无边框;设置元素的粘性属性为空字符串,表示不粘附在其他元素上。border=10, sticky='')'''notebook有如下状态可以设置disabled    禁用状态,该状态下的控件无法接收用户输入。normal      正常状态,该状态下的控件可以接收用户输入。active      激活状态(鼠标经过),该状态下的控件可以接收用户输入,并且会显示特殊效果(如闪烁)。selected    选中状态,该状态下的控件会显示特殊效果(如高亮)。insensitive 不敏感状态,该状态下的控件不会响应用户的键盘操作。focus       聚焦状态,该状态下的控件会显示特殊效果(如边框)。'''# 设置Notebook的样式为"CustomNotebook",并为"CustomNotebook.client"添加一个样式选项,设置其"sticky"属性为"nswe"style.layout("CustomNotebook", [("CustomNotebook.client", {"sticky": "nswe"})])# 设置CustomNotebook.Tab的布局样式style.layout("CustomNotebook.Tab", [("CustomNotebook.tab", { # 设置 CustomNotebook.tab 的样式"sticky": "nswe", # 设置 tab 的粘性属性为 NSWE,表示在水平方向上可拉伸,垂直方向上可滚动"children": [     # 设置 tab 的子元素("CustomNotebook.padding", { # 设置 CustomNotebook.padding 的样式"side": "top",      # 设置 padding 的侧边距在顶部"sticky": "nswe",   # 设置 padding 的粘性属性为 NSWE"children": [       # 设置 padding 的子元素("CustomNotebook.focus", { # 设置 CustomNotebook.focus 的样式"side": "top",    # 设置 focus 的侧边距在顶部"sticky": "nswe", # 设置 focus 的粘性属性为 NSWE"children": [     # 设置 focus 的子元素# 设置 CustomNotebook.label 的样式("CustomNotebook.label", {"side": "left", "sticky": ''}), # 设置 label 的侧边距在左侧,无粘性# 设置 CustomNotebook.close 的样式("CustomNotebook.close", {"side": "left", "sticky": ''}), # 设置 close 的侧边距在左侧,无粘性]})]})]})])

将定义好的Notebook应用到tk窗口,并添加存储标识,不需要的删除即可

if __name__ == "__main__":root = tk.Tk()notebook = CustomNotebook(width=400, height=400, padding=(2,5,2,2))notebook.pack(side="top", fill="both", expand=True)images = (# 原色tk.PhotoImage('save_original', data = '''R0lGODdhDgAOAIU9ADFjpTFjrTFjtTFrtTljrTlrrcDAwEJzvUpzvUp7vVJ7rVJ7vVqEvWOEvWOMzmuUzmuU1nOUxnOc1nOc3nuUxnucxnul53ut54Slzoylxoyl1oyt1ozGY5StxpS13py13qWtxqW9563G57XO773O78bW78bW987e9zlrvQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAADgAOAAAIjAAzUFhwIIXBgykYgDAQ4cQJFBAjQiThoEOCExdQOJA4kcSBAycsaOSIwkKJASlCkoQ4IYSAFCYsOHDwoOZMBxI+vIxpoWfPCRKC6kxRwqdPoEE9BEhBwqiFoFA3LG26EgUEDUtHiOTAtSuHBxiybvXK1UEFAAhEiKhagUIBCg0ODBBAN4DdAAAIKAgIADs='''),# 黑白tk.PhotoImage('save_gray', data = '''R0lGODdhDgAOAIU9AFxcXF1dXV9fX2JiYmRkZGVlZW1tbW9vb3R0dHZ2dn5+foGBgYeHh46Ojo+Pj5CQkJKSkpaWlpeXl6CgoKGhoaOjo6WlpaioqKmpqa2trbCwsLKysru7u8DAwMLCwsrKys3NzdTU1NXV1dzc3P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAADgAOAAAIiwApQEhgoIDBgwUUZOjwYMQIEhAjQgTB4AKCERZIMJA4EYQBAyMmaORIYkKIAQVCkoQogUOAAiImMGDQoOZMBhE2vIw5oWdPCRGC6iwQwqdPoEE1ACgAwuiEoFAvLG26koSDCks/iMTAtSuGBhOybvXKlYEEAAc8eKgqAQIBCAsMDAhAF4BduwIQBAQAOw=='''),# 红色tk.PhotoImage('save_red', data = '''R0lGODdhDgAOAIU9AP/h4f++vv+3t/+2tv+vr/+srP+kpP+iov+dnf+UlP+Skv+Pj/+Li/+Kiv+Hh/+Fhf+Dg/+Cgv95ef94eP90dP9ycv9xcf9wcP9paf9jY/9gYP9YWP9WVv9RUf9PT/tHR/pGRvhERPVBQfM/P/I+PgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAADgAOAAAIiwAhUNjg4YPBgx80LDhQIUAAABAjQiSAoQGHAA4AYJA4kYAHDwEiaOQIIMKAEB9CkoQoAcGIDwIiYMBwoeZMDBMSvIwZoWdPCROC6vwwwKdPoEEVkPhAwGiEoFAbLG26EoCFB0sLiGTAtSuDCxGybvXKFYMEEh0MGKgqgQIIChk8hBhBl4RduyI4BAQAOw=='''),# 淡红色tk.PhotoImage('save_lowred', data = '''R0lGODdhDgAOAIU9AP/w8P/p6f/o6P/h4f/e3v/W1v/U1P/Pz//Gxv/ExP/Bwf+9vf+8vP+5uf+3t/+1tf+0tP+rq/+qqv+mpv+kpP+jo/+iov+bm/+Vlf+Skv+Kiv+IiP+Dg/+Bgft5efp4ePh2dvVzc/NxcfJwcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAADgAOAAAIiwAhUNjg4YPBgx80LDhQIUAAABAjQiSAoQGHAA4AYJA4kYAHDwEiaOQIIMKAEB9CkoQoAcGIDwIiYMBwoeZMDBMSvIwZoWdPCROC6vwwwKdPoEEVkPhAwGiEoFAbLG26EoCFB0sLiGTAtSuDCxGybvXKFYMEEh0MGKgqgQIIChk8hBhBl4RduyI4BAQAOw=='''),)colour = {"blue":None, "red":None, "violet":None, "orange":None, "green":None}for color in colour.keys():colour[color] = tk.Frame(notebook, background=color) # 新建Frame作为标签内容notebook.add(colour[color], text=color) # 将新建的Frame添加到notebook生成一个标签colour['white'] = tk.Frame(notebook) notebook.add(colour['white'], text='white', image='save_gray' , compound='left') # 新建一个直接带image元素的标签,图标元素位于左侧notebook.insert(3, colour['white'])  #将'white'标签移动到3的位置notebook.select(colour['white'])# 修改标签的image元素notebook.tab(colour['blue']  , image='save_original', compound='left')notebook.tab(colour['red' ]  , image='save_red'     , compound='left')notebook.tab(colour['violet'], image='save_lowred'  , compound='left')root.mainloop()

上面代码中的base64编码的字符串,可以用下面代码获取,要用gif格式文件转换,传入文件路径即可。

from PIL import Image
import base64, io
def bmp_to_base64(img_path):"将gif图片转为base64编码的字符串"# 打开图片img = Image.open(img_path)# 将图片数据转为字节流byte_arr = io.BytesIO()img.save(byte_arr, format='GIF')img_bytes = byte_arr.getvalue()# 将字节流转为base64编码的字符串base64_str = base64.b64encode(img_bytes).decode()return base64_str
print (bmp_to_base64('gif文件路径'))

#想要拖动标签切换位置的可以绑定鼠标事件,自己试试吧。

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

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

相关文章

【力扣】42. 接雨水 <模拟、双指针、单调栈>

【力扣】42. 接雨水 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 目录 【力扣】42. 接雨水题解暴力双指针单调栈 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&…

数据结构<树和二叉树>顺序表存储二叉树实现堆排

✨Blog&#xff1a;&#x1f970;不会敲代码的小张:)&#x1f970; &#x1f251;推荐专栏&#xff1a;C语言&#x1f92a;、Cpp&#x1f636;‍&#x1f32b;️、数据结构初阶&#x1f480; &#x1f4bd;座右铭&#xff1a;“記住&#xff0c;每一天都是一個新的開始&#x1…

c语言实现MD5算法

MD5加密 文章目录 MD5加密MD5介绍应用场景代码分析 &#xff08;基于qt5.14.2&#xff09;测试记录 MD5介绍 1。 一种单向加密算法&#xff0c;即对明文加密&#xff0c;而不能通过密文得到明文。对原数据的任何改动&#xff0c;哪怕是1字节&#xff0c;得到的MD5值都有很大的区…

vue路由及打包部署

vue路由&#xff08;前端路由&#xff09;&#xff1a;URL中的hash&#xff08;#号&#xff09;与组件之间的对应关系。 一、安装vue路由 npm install vue-router3.5.1 二、定义路由表 路由表主要记录hash&#xff08;#号&#xff09;与组件之间的对应关系。主要定义在route…

FPGA:uart原理+tx发送模块+rx接收模块

文章目录 一、串口通信二、UART通信三、tx发送模块四、rx模块接收 一、串口通信 处理器与外部设备通信的两种方式&#xff1a; 串行通信&#xff1a; 指数据的各个位使用多条数据线同时进行传输。 并行通信&#xff1a; 将数据分成一位一位的形式在一条数据线上逐个传输。 串…

SQL Injection

SQL Injection 就是通过把恶意的sql命令插入web表单递交给服务器&#xff0c;或者输入域名或页面请求的查询字符串递交到服务器&#xff0c;达到欺骗服务器&#xff0c;让服务器执行这些恶意的sql命令&#xff0c;从而让攻击者&#xff0c;可以绕过一些机制&#xff0c;达到直…

sql server安装报错 合成活动模板库(ATL) 失败

错误 “合成活动模板库(ATL) 规则失败“ 解决办法&#xff1a; 进入SQL Server 2008R2安装包目录找到文件&#xff1a;sqlsupport_msi&#xff0c;安装此文件之后&#xff0c;再安装SQL Server&#xff0c;便可解决该问题。C:\SQL Server 2008R2\new\SQL Server 2008R2\2052_CH…

Java虚拟机(JVM):虚拟机栈溢出

一、概念 Java虚拟机栈溢出&#xff08;Java Virtual Machine Stack Overflow&#xff09;是指在Java程序中&#xff0c;当线程调用的方法层级过深&#xff0c;导致栈空间溢出的情况。 Java虚拟机栈是每个线程私有的&#xff0c;用于存储方法的调用和局部变量的内存空间。每当…

如何学习专业的学术用语01

问题的提出——凭啥人家写的词汇这么专业 做法一 做法二&#xff1a;做一个专业数据库 专门做教育技术类的

Android Ble蓝牙App(六)请求MTU与显示设备信息

前言 在上一篇文章中已经了解了数据操作的方式&#xff0c;而数据交互的字节长度取决于我们手机与蓝牙设备的最大支持长度。 目录 Ble蓝牙App&#xff08;一&#xff09;扫描Ble蓝牙App&#xff08;二&#xff09;连接与发现服务Ble蓝牙App&#xff08;三&#xff09;特性和属…

unity 之 Vector 数据类型

文章目录 Vector 1Vector 2Vector 3Vector 4 Vector 1 在Unity中&#xff0c;Vector1 并不是一个常见的向量类型。 如果您需要表示标量&#xff08;单个值&#xff09;或者只需要一维的数据&#xff0c;通常会直接使用浮点数&#xff08;float&#xff09;或整数&#xff08;in…

Linux命令200例:tail用来显示文件的末尾内容(常用)

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌。CSDN专家博主&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &…

【ARM】Day4 点亮LED灯

1. 思维导图 2. 自己编写代码实现三盏灯点亮 .text .global _start _start: /**********LED1&#xff0c;LED2,LED3点灯:PE10,PF10,PE8**************/ RCC_INIT:使能GPIOE组/GPIOF组控制器,通过RXCC_MP_AHB4ENSETR设置第[5:4]位写1,地址:0x50000A28[5:4]1ldr r0,0x50000A28 …

【深入探究人工智能】:常见机器学习算法总结

文章目录 1、前言1.1 机器学习算法的两步骤1.2 机器学习算法分类 2、逻辑回归算法2.1 逻辑函数2.2 逻辑回归可以用于多类分类2.3 逻辑回归中的系数 3、线性回归算法3.1 线性回归的假设3.2 确定线性回归模型的拟合优度3.3线性回归中的异常值处理 4、支持向量机&#xff08;SVM&a…

〔012〕Stable Diffusion 之 中文提示词自动翻译插件 篇

✨ 目录 🎈 翻译插件🎈 下载谷歌翻译🎈 谷歌翻译使用方法🎈 谷歌翻译使用效果🎈 翻译插件 在插件列表中搜索 Prompt Translator可以看到有2个插件选项:一个是基于谷歌翻译 〔推荐〕、一个基于百度和deepl翻译推荐使用谷歌翻译,因为是离线翻译,所以使用时不用在乎是…

Java之SpringCloud Alibaba【四】【微服务 Sentinel服务熔断】

Java之SpringCloud Alibaba【四】【微服务 Sentinel服务熔断】 一、分布式系统遇到的问题1、服务挂掉的一些原因 二、解决方案三、Sentinel&#xff1a;分布式系统的流量防卫兵1、Sentinel是什么2、Sentinel和Hystrix对比3、Sentinel快速开发4、通过注解的方式来控流5、启动Sen…

vue3 基础知识

vue3创建一个项目 PS D:\code> npm init vuelatestVue.js - The Progressive JavaScript Framework√ Add TypeScript? ... No / Yes √ Add JSX Support? ... No / Yes √ Add Vue Router for Single Page Application development? ... No / Yes √ Add Pinia for sta…

电商项目part04 微服务拆分

微服务架构拆分 微服务介绍 英文:https://martinfowler.com/articles/microservices.html 中文:http://blog.cuicc.com/blog/2015/07/22/microservices 微服务拆分时机 如下场景是否需要进行微服务拆分&#xff1f; 代码维护困难&#xff0c;几百人同时开发一个模块&…

小白的Node.js学习笔记大全---不定期更新

Node.js是什么 Node. js 是一个基于 Chrome v8 引擎的服务器端 JavaScript 运行环境Node. js 是一个事件驱动、非阻塞式I/O 的模型&#xff0c;轻量而又高效Node. js 的包管理器 npm 是全球最大的开源库生态系统 特性 单一线程 Node.js 沿用了 JavaScript 单一线程的执行特…

【数据结构】链表的回文结构

文章目录 &#x1f30f;引言&#x1f9ed;[链表的回文结构](https://www.nowcoder.com/practice/d281619e4b3e4a60a2cc66ea32855bfa?tpId49&&tqId29370&rp1&ru/activity/oj&qru/ta/2016test/question-ranking)&#x1f6a9;&#x1f6a9;题目描述&#xf…