Python Tkinter实现Notebook首个标签页内容复用至其余标签页
Tkinter Notebook 首个标签页内容同步到所有标签页解决方案
核心原理:Tkinter 单个控件实例只能归属一个父容器,不需要重复编写多套相同控件,通过标签切换事件动态迁移控件即可实现所有标签页复用同一套交互界面,控件状态自动同步,代码改动量最小。
操作步骤
- 移除原有代码中把输入框、列表框、按钮组固定挂载到
docks框架的写死逻辑,保留控件本身的样式、功能绑定不变。 - 给Notebook组件绑定标签切换事件
<<NotebookTabChanged>>,每次切换标签时,将所有公共控件重新布局到当前激活的标签页框架下。 - 调整文件读写逻辑,根据当前选中的标签名生成对应存储文件名,切换标签时自动加载对应标签的历史数据,避免不同标签内容混淆。
修改后可直接运行的完整代码
import tkinter from tkinter import * from tkinter import ttk from tkinter import END, ANCHOR # 定义字体和配色 text_color = "#fffacd" menu_color = "#6c769b" root_color = "#6c899a" button_color = "#6c898a" my_font = ("Times New Roman", 10) # 定义主窗口 root = tkinter.Tk() root.title("IT2Go NotePad") root.iconbitmap("pad.ico") root.geometry('500x500') root.config(bg=root_color) it2goNotebook = ttk.Notebook(root) it2goNotebook.pack(pady=15) # 创建所有标签页框架 tab_frames = { "Docks": Frame(it2goNotebook, width=500, height=500, bg=root_color), "KB Combo": Frame(it2goNotebook, width=500, height=500, bg=menu_color), "Monitors": Frame(it2goNotebook, width=500, height=500, bg=root_color), "Webcams": Frame(it2goNotebook, width=500, height=500, bg=menu_color), "Headsets": Frame(it2goNotebook, width=500, height=500, bg=root_color), "Pucks": Frame(it2goNotebook, width=500, height=500, bg=menu_color) } # 批量添加标签页 for tab_name, frame in tab_frames.items(): frame.pack(fill="both", expand=1) it2goNotebook.add(frame, text=tab_name) # 功能函数 def add_name(): """添加条目到列表框""" input_text = list_entry.get().strip() if input_text: my_listbox.insert(END, input_text) list_entry.delete(0, END) def remove_item(): """删除列表框选中条目""" selected = my_listbox.curselection() if selected: my_listbox.delete(selected) def save_list(): """保存当前标签列表到对应文件""" current_tab = it2goNotebook.tab(it2goNotebook.select(), "text") with open(f"{current_tab.lower().replace(' ', '_')}list.txt", 'w', encoding='utf-8') as f: list_tuple = my_listbox.get(0, END) for item in list_tuple: f.write(item.rstrip("\n") + "\n") def open_list(): """加载当前标签对应历史文件""" my_listbox.delete(0, END) current_tab = it2goNotebook.tab(it2goNotebook.select(), "text") try: with open(f"{current_tab.lower().replace(' ', '_')}list.txt", 'r', encoding='utf-8') as f: for line in f: my_listbox.insert(END, line.rstrip("\n")) except FileNotFoundError: return def on_tab_change(event): """标签切换时迁移公共控件到当前标签,加载对应数据""" # 先保存旧标签内容 save_list() # 获取当前激活的标签框架 current_frame = tab_frames[it2goNotebook.tab(it2goNotebook.select(), "text")] # 把控件重新挂载到当前框架 input_frame.master = current_frame button_frame.master = current_frame output_frame.master = current_frame input_frame.pack() output_frame.pack() button_frame.pack() # 加载当前标签的历史数据 open_list() # 初始化公共布局控件(所有标签复用,不需要重复创建多套) input_frame = tkinter.Frame(bg=menu_color) output_frame = tkinter.Frame(bg=menu_color) button_frame = tkinter.Frame(bg=button_color) # 输入区布局 list_entry = tkinter.Entry(input_frame, width=41, borderwidth=5, font=my_font) list_add_button = tkinter.Button(input_frame, text="Add A Name", borderwidth=5, font=my_font, bg=button_color, command=add_name) list_entry.grid(row=0, column=0) list_add_button.grid(row=0, column=1, padx=2, pady=5, ipadx=5) # 列表展示区布局 my_scrollbar = tkinter.Scrollbar(output_frame) my_listbox = tkinter.Listbox(output_frame, height=15, width=60, borderwidth=3, font=my_font, yscrollcommand=my_scrollbar.set) my_scrollbar.config(command=my_listbox.yview) my_listbox.grid(row=0, column=0) my_scrollbar.grid(row=0, column=1, sticky=NS) # 按钮区布局 remove_item_button = tkinter.Button(button_frame, text="Remove Name", borderwidth=5, font=my_font, bg=button_color, command=remove_item) save_button = tkinter.Button(button_frame, text="Save", borderwidth=5, font=my_font, bg=button_color, command=save_list) quit_button = tkinter.Button(button_frame, text="Quit", borderwidth=5, font=my_font, bg=button_color, command=root.destroy) remove_item_button.grid(row=0, column=1, padx=5, pady=5, ipadx=5) save_button.grid(row=0, column=2, padx=5, pady=5, ipadx=30) quit_button.grid(row=0, column=3, padx=5, pady=5, ipadx=30) # 绑定标签切换事件 it2goNotebook.bind("<<NotebookTabChanged>>", on_tab_change) # 初始加载第一个标签页内容 on_tab_change(None) # 运行主循环 root.mainloop()
代码说明:所有标签页完全复用同一套输入、列表、按钮控件,不需要为每个标签重复编写布局代码,切换标签时自动保存旧标签数据、加载新标签数据,完全满足复用要求。
内容的提问来源于stack exchange,提问作者ManWithDirtyGlasses
相关产品推荐
相关产品推荐

