Skip to main content
 首页 » 编程设计

python之有没有办法将关闭按钮添加到 tkinter.ttk.Notebook 中的选项卡

2025年05月04日9insus

我想为 tkinter.ttk.Notebook 中的每个选项卡添加关闭按钮。我已经尝试添加图像并对点击事件使用react,但不幸的是 BitmapImage 没有 bind() 方法。

如何修复此代码?

#!/usr/binenv python3 
 
from tkinter import * 
from tkinter.ttk import * 
 
 
class Application(Tk): 
    def __init__(self): 
        super().__init__() 
        notebook = Notebook(self) 
        notebook.pack(fill=BOTH, expand=True) 
        self.img = BitmapImage(master=self, file='./image.xbm') 
        self.img.bind('<Button-1>', self._on_click) 
        notebook.add(Label(notebook, text='tab content'), text='tab caption', image=self.img) 
 
    def _on_click(self, event): 
        print('it works') 
 
app = Application() 
app.mainloop() 

图片.xbm

#define bullet_width 11 
#define bullet_height 9 
static char bullet_bits = { 
    0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00 
} 

请您参考如下方法:

主题 (ttk) 小部件的一个优点是您可以从各个小部件“元素”创建新的小部件。虽然不是很简单(也没有详细记录),但您可以创建一个新的“关闭选项卡”元素,将其添加到“选项卡”元素。

我将介绍一种可能的解决方案。我承认这不是特别容易理解。也许可以在 tkdocs.com 上找到有关如何创建自定义小部件样式的最佳资源之一,从 Styles and Themes 开始。部分。

try: 
    import Tkinter as tk 
    import ttk 
except ImportError:  # Python 3 
    import tkinter as tk 
    from tkinter import ttk 
 
class CustomNotebook(ttk.Notebook): 
    """A ttk Notebook with close buttons on each tab""" 
 
    __initialized = False 
 
    def __init__(self, *args, **kwargs): 
        if not self.__initialized: 
            self.__initialize_custom_style() 
            self.__inititialized = True 
 
        kwargs["style"] = "CustomNotebook" 
        ttk.Notebook.__init__(self, *args, **kwargs) 
 
        self._active = None 
 
        self.bind("<ButtonPress-1>", self.on_close_press, True) 
        self.bind("<ButtonRelease-1>", self.on_close_release) 
 
    def on_close_press(self, event): 
        """Called when the button is pressed over the close button""" 
 
        element = self.identify(event.x, event.y) 
 
        if "close" in element: 
            index = self.index("@%d,%d" % (event.x, event.y)) 
            self.state(['pressed']) 
            self._active = index 
            return "break" 
 
    def on_close_release(self, event): 
        """Called when the button is released""" 
        if not self.instate(['pressed']): 
            return 
 
        element =  self.identify(event.x, event.y) 
        if "close" not in element: 
            # user moved the mouse off of the close button 
            return 
 
        index = self.index("@%d,%d" % (event.x, event.y)) 
 
        if self._active == index: 
            self.forget(index) 
            self.event_generate("<<NotebookTabClosed>>") 
 
        self.state(["!pressed"]) 
        self._active = None 
 
    def __initialize_custom_style(self): 
        style = ttk.Style() 
        self.images = ( 
            tk.PhotoImage("img_close", data=''' 
                R0lGODlhCAAIAMIBAAAAADs7O4+Pj9nZ2Ts7Ozs7Ozs7Ozs7OyH+EUNyZWF0ZWQg 
                d2l0aCBHSU1QACH5BAEKAAQALAAAAAAIAAgAAAMVGDBEA0qNJyGw7AmxmuaZhWEU 
                5kEJADs= 
                '''), 
            tk.PhotoImage("img_closeactive", data=''' 
                R0lGODlhCAAIAMIEAAAAAP/SAP/bNNnZ2cbGxsbGxsbGxsbGxiH5BAEKAAQALAAA 
                AAAIAAgAAAMVGDBEA0qNJyGw7AmxmuaZhWEU5kEJADs= 
                '''), 
            tk.PhotoImage("img_closepressed", data=''' 
                R0lGODlhCAAIAMIEAAAAAOUqKv9mZtnZ2Ts7Ozs7Ozs7Ozs7OyH+EUNyZWF0ZWQg 
                d2l0aCBHSU1QACH5BAEKAAQALAAAAAAIAAgAAAMVGDBEA0qNJyGw7AmxmuaZhWEU 
                5kEJADs= 
            ''') 
        ) 
 
        style.element_create("close", "image", "img_close", 
                            ("active", "pressed", "!disabled", "img_closepressed"), 
                            ("active", "!disabled", "img_closeactive"), border=8, sticky='') 
        style.layout("CustomNotebook", [("CustomNotebook.client", {"sticky": "nswe"})]) 
        style.layout("CustomNotebook.Tab", [ 
            ("CustomNotebook.tab", { 
                "sticky": "nswe", 
                "children": [ 
                    ("CustomNotebook.padding", { 
                        "side": "top", 
                        "sticky": "nswe", 
                        "children": [ 
                            ("CustomNotebook.focus", { 
                                "side": "top", 
                                "sticky": "nswe", 
                                "children": [ 
                                    ("CustomNotebook.label", {"side": "left", "sticky": ''}), 
                                    ("CustomNotebook.close", {"side": "left", "sticky": ''}), 
                                ] 
                        }) 
                    ] 
                }) 
            ] 
        }) 
    ]) 
 
if __name__ == "__main__": 
    root = tk.Tk() 
 
    notebook = CustomNotebook(width=200, height=200) 
    notebook.pack(side="top", fill="both", expand=True) 
 
    for color in ("red", "orange", "green", "blue", "violet"): 
        frame = tk.Frame(notebook, background=color) 
        notebook.add(frame, text=color) 
 
    root.mainloop() 

这是它在 linux 系统上的样子: