タブに閉じるボタンを実装する方法が思いつかず調べているとStackflowでこのようなコードを見つけました。[参考元]
py
1import tkinter as tk 2from tkinter import ttk 3 4class CustomNotebook(ttk.Notebook): 5 """A ttk Notebook with close buttons on each tab""" 6 7 __initialized = False 8 9 def __init__(self, *args, **kwargs): 10 if not self.__initialized: 11 self.__initialize_custom_style() 12 self.__inititialized = True 13 14 kwargs["style"] = "CustomNotebook" 15 ttk.Notebook.__init__(self, *args, **kwargs) 16 17 self._active = None 18 19 self.bind("<ButtonPress-1>", self.on_close_press, True) 20 self.bind("<ButtonRelease-1>", self.on_close_release) 21 22 def on_close_press(self, event): 23 """Called when the button is pressed over the close button""" 24 25 element = self.identify(event.x, event.y) 26 27 if "close" in element: 28 index = self.index("@%d,%d" % (event.x, event.y)) 29 self.state(['pressed']) 30 self._active = index 31 return "break" 32 33 def on_close_release(self, event): 34 """Called when the button is released""" 35 if not self.instate(['pressed']): 36 return 37 38 element = self.identify(event.x, event.y) 39 if "close" not in element: 40 # user moved the mouse off of the close button 41 return 42 43 index = self.index("@%d,%d" % (event.x, event.y)) 44 45 if self._active == index: 46 self.forget(index) 47 self.event_generate("<<NotebookTabClosed>>") 48 49 self.state(["!pressed"]) 50 self._active = None 51 52 def __initialize_custom_style(self): 53 style = ttk.Style() 54 self.images = ( 55 tk.PhotoImage("img_close", data=''' 56 R0lGODlhCAAIAMIBAAAAADs7O4+Pj9nZ2Ts7Ozs7Ozs7Ozs7OyH+EUNyZWF0ZWQg 57 d2l0aCBHSU1QACH5BAEKAAQALAAAAAAIAAgAAAMVGDBEA0qNJyGw7AmxmuaZhWEU 58 5kEJADs= 59 '''), 60 tk.PhotoImage("img_closeactive", data=''' 61 R0lGODlhCAAIAMIEAAAAAP/SAP/bNNnZ2cbGxsbGxsbGxsbGxiH5BAEKAAQALAAA 62 AAAIAAgAAAMVGDBEA0qNJyGw7AmxmuaZhWEU5kEJADs= 63 '''), 64 tk.PhotoImage("img_closepressed", data=''' 65 R0lGODlhCAAIAMIEAAAAAOUqKv9mZtnZ2Ts7Ozs7Ozs7Ozs7OyH+EUNyZWF0ZWQg 66 d2l0aCBHSU1QACH5BAEKAAQALAAAAAAIAAgAAAMVGDBEA0qNJyGw7AmxmuaZhWEU 67 5kEJADs= 68 ''') 69 ) 70 71 style.element_create("close", "image", "img_close", 72 ("active", "pressed", "!disabled", "img_closepressed"), 73 ("active", "!disabled", "img_closeactive"), border=8, sticky='') 74 style.layout("CustomNotebook", [("CustomNotebook.client", {"sticky": "nswe"})]) 75 style.layout("CustomNotebook.Tab", [ 76 ("CustomNotebook.tab", { 77 "sticky": "nswe", 78 "children": [ 79 ("CustomNotebook.padding", { 80 "side": "top", 81 "sticky": "nswe", 82 "children": [ 83 ("CustomNotebook.focus", { 84 "side": "top", 85 "sticky": "nswe", 86 "children": [ 87 ("CustomNotebook.label", {"side": "left", "sticky": ''}), 88 ("CustomNotebook.close", {"side": "left", "sticky": ''}), 89 ] 90 }) 91 ] 92 }) 93 ] 94 }) 95 ]) 96 97if __name__ == "__main__": 98 root = tk.Tk() 99 100 notebook = CustomNotebook(width=200, height=200) 101 notebook.pack(side="top", fill="both", expand=True) 102 103 for color in ("red", "orange", "green", "blue", "violet"): 104 frame = tk.Frame(notebook, background=color) 105 notebook.add(frame, text=color) 106 107 root.mainloop()
import部分がそのままだと動かないためそこだけ編集しましたがそれ以外はそのままで動かしたところ×ボタンにカーソルを合わせたらデザインが変わるのではなく,タブにカーソルを合わしたらデザインが変わるようなものでした。
確かにCustomNotebook.focus
の子要素にstyle.element_create
で追加したclose
を"active", "!disabled", "img_closeactive"
とNotebookのStateでデザインを変えているのは理解できてはいるのですが,×ボタンにカーソルを合わせたらデザインが変えるようにするためにはどのような方法があるのかがわかりませんでした。
そもそもStyleよりもthemeを使うべきなのかな?とか調べていて思ったりしたのですが何かヒントをいただけるとありがたいです。
追記 2021/10/24 01:14
実装したい細かいこと
0. カーソルを×ボタンに合わせると黄色い×になる。
- カーソルを×ボタンに合わせながらクリックすると赤いボタンになる。
- 通常時は黒い×である。
追記(解決コード)
一部変更点ありますが,以下のコードで実装出来ました!
py
1class CustomNotebook(ttk.Notebook): 2 """A ttk Notebook with close buttons on each tab""" 3 4 __initialized = False 5 6 def __init__(self, *args, **kwargs): 7 if not self.__initialized: 8 self.__initialize_custom_style() 9 self.__inititialized = True 10 11 kwargs["style"] = "CustomNotebook" 12 ttk.Notebook.__init__(self, *args, **kwargs) 13 14 self._active = None 15 16 self.bind("<ButtonPress-1>", self.on_close_press, True) 17 self.bind("<ButtonRelease-1>", self.on_close_release) 18 self.bind("<Motion>", self.on_close_motion) 19 20 def on_close_motion(self, event): 21 element = self.identify(event.x, event.y) 22 if "close" in element: 23 self.state(['!pressed']) 24 self.state(['hover']) 25 else: 26 self.state(['!pressed']) 27 self.state(['!hover']) 28 29 def on_close_press(self, event): 30 """Called when the button is pressed over the close button""" 31 32 element = self.identify(event.x, event.y) 33 34 if "close" in element: 35 index = self.index("@%d,%d" % (event.x, event.y)) 36 self.state(['pressed']) 37 self.state(['hover']) 38 self._active = index 39 return "break" 40 41 def on_close_release(self, event): 42 """Called when the button is released""" 43 if not self.instate(['pressed']) and not self.instate(['hover']): 44 print("bbb") 45 return 46 47 element = self.identify(event.x, event.y) 48 if "close" not in element: 49 # user moved the mouse off of the close button 50 self.state(['!pressed']) 51 self.state(['!hover']) 52 print("aaa") 53 return 54 55 index = self.index("@%d,%d" % (event.x, event.y)) 56 57 if self._active == index: 58 close_file(index) 59 60 self.state(["!pressed"]) 61 self.state(['!hover']) 62 self._active = None 63 64 def __initialize_custom_style(self): 65 img_close = image_file_to_base64(settings.resource_path("icon/tab/closeTabButton.gif")) 66 img_closehover = image_file_to_base64(settings.resource_path("icon/tab/closeTabButton_hover.gif")) 67 img_closepressed = image_file_to_base64(settings.resource_path("icon/tab/closeTabButton_push.gif")) 68 img_closeintact = image_file_to_base64(settings.resource_path("icon/tab/closeTabButton_inact.gif")) 69 70 style = ttk.Style() 71 self.images = ( 72 # 73 tk.PhotoImage("img_close", data=img_close), 74 tk.PhotoImage("img_closehover", data=img_closehover), 75 tk.PhotoImage("img_closepressed", data=img_closepressed), 76 tk.PhotoImage("img_closeintact", data=img_closeintact) 77 ) 78 79 style.element_create( 80 "close", "image", "img_close", 81 ("!active", "!selected", "img_closeintact"), 82 ("active", "!pressed", "hover", "!disabled", "img_closehover"), 83 ("active", "pressed", "hover", "!disabled", "img_closepressed"), 84 ("active", "!pressed", "!hover", "!disabled", "img_close"), 85 border=8, sticky='' 86 ) 87 style.layout("CustomNotebook", [("CustomNotebook.client", {"sticky": "nswe"})]) 88 style.layout("CustomNotebook.Tab", [ 89 ("CustomNotebook.tab", { 90 "sticky": "nswe", 91 "children": [ 92 ("CustomNotebook.padding", { 93 "side": "top", 94 "sticky": "nswe", 95 "children": [ 96 ("CustomNotebook.focus", { 97 "side": "top", 98 "sticky": "nswe", 99 "children": [ 100 ("CustomNotebook.label", {"side": "left", "sticky": ''}), 101 ("CustomNotebook.close", {"side": "left", "sticky": ''}), 102 ] 103 }) 104 ] 105 }) 106 ] 107 }) 108 ])
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/10/23 16:26 編集
2021/10/23 16:35 編集
2021/10/24 03:57
2021/10/24 04:28 編集
2021/10/24 04:42 編集
2021/10/24 04:55 編集
2021/10/24 05:54 編集
2021/10/24 06:46
2021/10/24 07:02