如何通过按钮调用实现Tkinter Notebook组件的叠加切换?
Hey there! I see you're trying to toggle between two Notebook components using buttons but having trouble getting them to switch properly. Let's break down the issues in your code and fix them step by step.
Key Issues in Your Current Code
- Duplicate component creation: Each button click runs a function that makes a brand new Frame and Notebook. The old components don't disappear—they just stack on top of each other, leading to messy overlaps.
- Incorrect command binding: Writing
command=self.Create_NoteBook_1()runs the function immediately when the button is created, not when you click it. You need to pass the function reference without parentheses. - No way to track existing components: You don't store references to the Frames/Notebooks as class variables, so you can't hide or show them later.
Solution: Track Components & Toggle Visibility
Here's a revised version of your code that fixes these problems. We'll:
- Store Notebook containers as class instance variables to track their state.
- Create Notebooks once (on first click) instead of every time you press a button.
- Add toggle logic to hide the active Notebook and show the target one.
- Fix the button command binding issue.
import tkinter as tk from tkinter import ttk class MainFrame(tk.Tk): def __init__(self): # Fix main window initialization (you had duplicate Tk instances before!) super().__init__() Main_Title = "Test : notebook overlay" self.geometry("700x550") self.resizable(False, False) self.wm_title(Main_Title) self.configure(bg = "CadetBlue1") # Initialize instance variables to hold our Notebook containers self.frame_notebook1 = None self.frame_notebook2 = None # Create all UI widgets self.Create_Widgets() def Create_Widgets(self): # Exit button Button_Quit = tk.Button(self, text="Exit", width=20, height=2, command=self.destroy ) Button_Quit.place(x= 20, y= 500) # Notebook 1 button - fix command binding (no parentheses!) Button_NoteBook1 = tk.Button(self, text="NoteBook 1", width = 20, height = 2, command=self.show_notebook1) Button_NoteBook1.place(x = 150, y = 20) # Notebook 2 button Button_NoteBook2 = tk.Button(self, text="NoteBook 2", width = 20, height = 2, command=self.show_notebook2) Button_NoteBook2.place(x = 350, y = 20) def create_notebook1(self): # Create Notebook 1 and its tabs self.frame_notebook1 = tk.Frame(self, width = 660, height = 400, bg = "OliveDrab1") self.frame_notebook1.place(x = 20, y = 80) Tab_List1 = ["Name 11", "Name 12", "Name 13", "Name 14", "Name 15", "Name 16"] NoteBook1 = ttk.Notebook(self.frame_notebook1) # Use relwidth/relheight to make the Notebook fill its parent frame NoteBook1.place(x = 0, y= 0, relwidth=1, relheight=1) for tab_text in Tab_List1: tab = ttk.Frame(NoteBook1) NoteBook1.add(tab, text=tab_text) def create_notebook2(self): # Create Notebook 2 and its tabs self.frame_notebook2 = tk.Frame(self, width = 660, height = 400, bg = "sandy brown") self.frame_notebook2.place(x = 20, y = 80) Tab_List2 = ["Name 21", "Name 22", "Name 23"] NoteBook2 = ttk.Notebook(self.frame_notebook2) NoteBook2.place(x = 0, y= 0, relwidth=1, relheight=1) for tab_text in Tab_List2: tab = ttk.Frame(NoteBook2) NoteBook2.add(tab, text=tab_text) def show_notebook1(self): # Hide Notebook 2 if it exists if self.frame_notebook2: self.frame_notebook2.place_forget() # Create Notebook 1 if it doesn't exist yet, then show it if not self.frame_notebook1: self.create_notebook1() else: self.frame_notebook1.place(x = 20, y = 80) def show_notebook2(self): # Hide Notebook 1 if it exists if self.frame_notebook1: self.frame_notebook1.place_forget() # Create Notebook 2 if it doesn't exist yet, then show it if not self.frame_notebook2: self.create_notebook2() else: self.frame_notebook2.place(x = 20, y = 80) if __name__ == "__main__": app = MainFrame() app.mainloop()
What Changed?
- Fixed main window setup: You were creating two separate
Tk()instances, which causes unexpected Tkinter behavior. We usesuper().__init__()to properly initialize the main window. - Instance variables for frames:
self.frame_notebook1andself.frame_notebook2let us track if the frames exist and control their visibility. - Lazy loading: Notebooks are only created once (on first click) instead of every time you press the button, which saves resources.
- Toggle logic:
show_notebook1()andshow_notebook2()hide the opposite frame (usingplace_forget()) and show the target frame—no more overlapping components. - Corrected command binding: Buttons now reference functions without parentheses, so they only run when clicked.
This should let you switch between the two Notebooks smoothly with just a click of the buttons!
内容的提问来源于stack exchange,提问作者DIEVAL




