通过Python tkinter实现类似Notepad++页面的效果,包括在Notebook标签中添加关闭按钮元素和存储状态提示图标,展示当前页面和鼠标交互效果。
效果图展示
粉色框是当前页面,橙色框是鼠标经过,红色框是按下按钮,灰色按钮是其他页面的效果;
存储标识可以用来识别页面是否存储:例如当前页面已经保存用蓝色,未保存用红色,其他页面已经保存用灰色,未保存用淡红色。文章来源:https://www.toymoban.com/news/detail-654019.html
首先导入模块
import tkinter as tkfrom 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 = True # 标记__initialized,防止第二次调用出错 # 设置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 = index def on_close_release(self, event): """ 当鼠标在关闭按钮上释放时调用此方法。 event: 包含鼠标事件信息的对象。 """ if not self.instate(['pressed']): # 如果按钮没有按下状态,直接返回 return try: 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: pass self.state(["!pressed"]) # 将按钮状态设置为非按下状态 self._active = None # 将当前激活的标签页设置为None def __initialize_custom_style(self): # 创建一个ttk样式对象 style = ttk.Style() # 定义四个图片对象,分别表示关闭按钮的不同状态 self.images = ( # 元素普通状态时图标 tk.PhotoImage("img_closenormal", data=''' R0lGODdhCwALAIMAAJKSkpeXl5ubm5+fn6CgoKampqqqqq2trbGxsba2tr29vcHBwdnZ2QAAAAAAAAAA ACwAAAAACwALAAAIXQAXJEBwwEDBAgUGHEigYOCBhwYMEBCAIAEDBgYQXhwg4ACCiwwKgOQIEeRGjgUK GgBJYABKgyYZuBRAQORFmwwEBBhgE6FNAQAEDCBAtCVHoAcC6AzANAAAAAYCAgA7 '''), # 选中的选项卡的关闭图标 tk.PhotoImage("img_closeselected", data=''' R0lGODdhCwALAIVUAJ9dcptfe6NfcpthfZ5hfJ9ifp5nfaNjda9lc6Rmea1nfqRpe6Fqfq9ofK1ofqxr frFndbJqeLJufZ9rgKpngaBqgKtpg6tphK5uhKxvia5xhq91iq1xjK1zj692jLFyg7N1hrJ3i7B2jbF4 ja51ka94kq97l698mq9+m7B8mbB/nLCDn6aEoayMprCForGMq7KNq7KPrrOXt7WfwP///wAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAACwALAAAIcgBnwFiBwoQJEh0yUGARQ8YLFwRPHLwQ wEUMGjQOcsB4YYAKFxhpbMRooYCJFSlCYlTgoAAJFSlMhHTgQEGBDilSqoyggACGEiFFhGxwAINQGiNC gMAIQcADDR48bAjxQUIEBABaGJgwoQKDBQkOCGAREAA7 '''), # 鼠标经过时选项卡的关闭图标 tk.PhotoImage("img_closeactive", data=''' R0lGODdhCwALAIVSAN5IN+lRNeBQP+5bPvtSP+FSQuJXR+VbRu5dQetfRuVbSf9dS/xeTO5iR+hhTOxl TP1wTP1iUP1kUv9lVPxnVv9rVP1pWP9rWv9vXv5/WP54Xf9yYv11YP90ZP99YP94af97bP99bv6BW/6C Yv6FYP+BZf6JZv+Eb/6Jav+Oa+eJe/+Bcf+Edf+Hef+KfP+Rd/+WfP+bev+Pgu+Rhv+RhP+ViP+Zjf+h lv+lmv+1rP+/twAAAAAAAAAAAAAAACwAAAAACwALAAAIcwB13KDhgkWIEB8wRJiBIwcOGzRktFjx wUKBGjh27GABYoNGCQZc2NC4owNJkCsIktRYoYKCDywmkizhQYODDSFWrNyRYsSDCSY1wiBJosGCCxpP vIihMcMAAgwoXOBQAoUJERACzAAAoICAAwkaIAigIiAAOw== '''), # 按下关闭按钮时选项卡的关闭图标 tk.PhotoImage("img_closepressed", data=''' R0lGODdhCwALAIUAAGsiD20jEHIkEHYlEXsnEX4oEogrE4orFIwsFJEtFJUvFZoxFpwwFp4yF6EzF6Yz F642GbU3GbY4Grk5Grk6G7s7G7w6G7w8G8A+HcJAHcVDH8ZEH8dEIMhGIMtJIsxKIs1KIpdxZ8eAbtqI cuKdiQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAACwALAAAIcABDABBA4AACBQscNBARIAGDBxAkVKhw oeIABiRIRJhQIeMFDAUeZCTRMWOGCwYgRBhpMgMGBBEqWBipYcOGDAoolBz5wcOGBRdGchjps0FQEhk6 eMgIgoODihgycOgAAoQHDiIsYMBwoeYGDhtGBAQAOw== '''), ) # 使用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 = ''' R0lGODdhDgAOAIU9ADFjpTFjrTFjtTFrtTljrTlrrcDAwEJzvUpzvUp7vVJ7rVJ7vVqEvWOEvWOMzmuU zmuU1nOUxnOc1nOc3nuUxnucxnul53ut54Slzoylxoyl1oyt1ozGY5StxpS13py13qWtxqW9563G57XO 773O78bW78bW987e9zlrvQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAADgAOAAAIjAAzUFhwIIXBgykYgDAQ4cQJFBAjQiTh oEOCExdQOJA4kcSBAycsaOSIwkKJASlCkoQ4IYSAFCYsOHDwoOZMBxI+vIxpoWfPCRKC6kxRwqdPoEE9 BEhBwqiFoFA3LG26EgUEDUtHiOTAtSuHBxiybvXK1UEFAAhEiKhagUIBCg0ODBBAN4DdAAAIKAgIADs= '''), # 黑白 tk.PhotoImage('save_gray', data = ''' R0lGODdhDgAOAIU9AFxcXF1dXV9fX2JiYmRkZGVlZW1tbW9vb3R0dHZ2dn5+foGBgYeHh46Ojo+Pj5CQ kJKSkpaWlpeXl6CgoKGhoaOjo6WlpaioqKmpqa2trbCwsLKysru7u8DAwMLCwsrKys3NzdTU1NXV1dzc 3P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAADgAOAAAIiwApQEhgoIDBgwUUZOjwYMQIEhAjQgTB 4AKCERZIMJA4EYQBAyMmaORIYkKIAQVCkoQogUOAAiImMGDQoOZMBhE2vIw5oWdPCRGC6iwQwqdPoEE1 ACgAwuiEoFAvLG26koSDCks/iMTAtSuGBhOybvXKlYEEAAc8eKgqAQIBCAsMDAhAF4BduwIQBAQAOw== '''), # 红色 tk.PhotoImage('save_red', data = ''' R0lGODdhDgAOAIU9AP/h4f++vv+3t/+2tv+vr/+srP+kpP+iov+dnf+UlP+Skv+Pj/+Li/+Kiv+Hh/+F hf+Dg/+Cgv95ef94eP90dP9ycv9xcf9wcP9paf9jY/9gYP9YWP9WVv9RUf9PT/tHR/pGRvhERPVBQfM/ P/I+PgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAADgAOAAAIiwAhUNjg4YPBgx80LDhQIUAAABAjQiSA oQGHAA4AYJA4kYAHDwEiaOQIIMKAEB9CkoQoAcGIDwIiYMBwoeZMDBMSvIwZoWdPCROC6vwwwKdPoEEV kPhAwGiEoFAbLG26EoCFB0sLiGTAtSuDCxGybvXKFYMEEh0MGKgqgQIIChk8hBhBl4RduyI4BAQAOw== '''), # 淡红色 tk.PhotoImage('save_lowred', data = ''' R0lGODdhDgAOAIU9AP/w8P/p6f/o6P/h4f/e3v/W1v/U1P/Pz//Gxv/ExP/Bwf+9vf+8vP+5uf+3 t/+1tf+0tP+rq/+qqv+mpv+kpP+jo/+iov+bm/+Vlf+Skv+Kiv+IiP+Dg/+Bgft5efp4ePh2dvVzc/Nx cfJwcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAADgAOAAAIiwAhUNjg4YPBgx80LDhQIUAAABAjQiSA oQGHAA4AYJA4kYAHDwEiaOQIIMKAEB9CkoQoAcGIDwIiYMBwoeZMDBMSvIwZoWdPCROC6vwwwKdPoEEV kPhAwGiEoFAbLG26EoCFB0sLiGTAtSuDCxGybvXKFYMEEh0MGKgqgQIIChk8hBhBl4RduyI4BAQAOw== '''), ) 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 Imageimport base64, iodef 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_strprint (bmp_to_base64('gif文件路径'))
#想要拖动标签切换位置的可以绑定鼠标事件,自己试试吧。文章来源地址https://www.toymoban.com/news/detail-654019.html
到了这里,关于Python tkinter Notebook标签添加关闭按钮元素及存储状态提示图标案例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!