使用Tkinter Notebook组件时如何重置窗口大小?
Tkinter Notebook标签页切换后窗口尺寸无法自适应问题
我知道这个问题之前有人提过,但目前能找到的解决方案都不管用。
具体场景
- 开发一个包含3个ttk.Notebook标签页的应用,三个标签页初始内容尺寸不同:第二个标签页最小,第三个最大。
- 采用grid布局,切换标签时出现以下问题:
- 从第一个标签页切换到第二个时,窗口会残留多余空白区域(因为第一个标签页内容比第二个稍大);
- 从第三个标签页切换到第二个/第一个时,窗口仍会保持第三个标签页的尺寸,不会自动缩小适配当前标签内容。
相关代码
# Tk modules import tkinter as tk from tkinter import ttk # # define main() def main(): app = App() MainWindow(app) app.mainloop() # Frame for data input class RegisterChooseType(ttk.Frame): def __init__(self, container): # Inheritance super().__init__(container) self.container = container # Var for selection self.selected_value = tk.IntVar() # Options self.options = {"padx": 10, "pady": 10} # Doc types self.doc_types = ("Incoming Bill", "Outgoing Bill", "Contract", "Other") # Labels self.barcode_label = ttk.Label(self, text="Barcode:").grid( row=0, column=0, sticky="EW", **self.options ) self.doc_type_label = ttk.Label(self, text="Document type:").grid( row=0, column=2, sticky=tk.W, **self.options ) # Entries self.barcode_entry = ttk.Entry(self) self.barcode_entry.grid(row=0, column=1, sticky="EW", **self.options) self.grid() def submit(self): self.current_dict["func"](self, self.current_frame) class DeleteTab(ttk.Frame): def __init__(self, container): # Inheritance super().__init__(container) # self.columnconfigure(0, weight=1) # self.columnconfigure(1, weight=1) self.options = {"padx": 10, "pady": 10} ## Type Barcode # Label self.barcode_label = ttk.Label(self, text="Barcode:").grid( row=0, column=0, sticky="EW", **self.options ) # Entries self.barcode_entry = ttk.Entry(self) self.barcode_entry.grid(row=0, column=1, sticky="EW", **self.options) # self.pack(fill="x") self.grid(sticky="W") class ViewTab(ttk.Frame): def __init__(self, container): # Inheritance super().__init__(container) self.container = container self.options = {"padx": 10, "pady": 10} # Doc types self.doc_types = ("Incoming Bill", "Outgoing Bill", "Contract", "Other") ## Type Barcode # Labels # Barcode self.barcode_label = ttk.Label(self, text="Barcode:") self.barcode_label.grid(row=0, column=0, sticky="EW", **self.options) # Document type self.doc_type_label = ttk.Label(self, text="Document Type:") self.doc_type_label.grid(row=0, column=2, sticky="EW", **self.options) # Entries # Barcode self.barcode_entry = ttk.Entry(self) self.barcode_entry.grid(row=0, column=1, sticky="EW", **self.options) # Document type self.doc_type_comb = ttk.Combobox(self) self.doc_type_comb["state"] = "readonly" # Doesn't allow new entries self.doc_type_comb["values"] = self.doc_types self.doc_type_comb.grid( row=0, column=3, columnspan=3, sticky=tk.EW, **self.options ) ## View Button self.viewSubmitButton = ttk.Button( self, text="View", command=lambda: print("View") ) self.viewSubmitButton.grid( column=4, row=self.grid_size()[0], sticky="EW", **self.options, ) # New LabelFrame self.deliver_view_LabelFrame = ttk.LabelFrame(self) self.deliver_view_LabelFrame["text"] = "View Document" self.deliver_view_LabelFrame.grid( row=1, columnspan=self.grid_size()[0], column=0, sticky="ew", padx=10, pady=10, ) # Inside LabelFrame ##TreeView self.dataDisplay = ttk.Treeview(self.deliver_view_LabelFrame, show="") self.dataDisplay.pack(fill="x", **self.options) self.grid(sticky="ews") # Create window class MainWindow: def __init__(self, container): self.container = container ## Create Parent self.tab_parent = ttk.Notebook() self.tab_parent.enable_traversal() # Create tab frames self.tab_register = ttk.Frame(self.tab_parent) self.tab_view = ttk.Frame(self.tab_parent) self.tab_delete = ttk.Frame(self.tab_parent) # Adding the tabs to the main object (self.tab_parent) self.tab_parent.add(self.tab_register, text="Register Documents") self.tab_parent.add(self.tab_delete, text="Delete Documents") self.tab_parent.add(self.tab_view, text="View Documents") # Create empt variables self.current_tab = None self.last_tab = None # Focus on barcode # self.register.barcode_entry.focus() self.tab_parent.bind("<<NotebookTabChanged>>", self.on_tab_change) # Pack notebook # self.tab_parent.pack(expand=True, fill="x", side="left") self.tab_parent.grid(sticky="e") ## Triggers when changing tabs def on_tab_change(self, event): if self.current_tab != None: self.current_tab.destroy() # Get the current tab name selected = event.widget.tab("current")["text"] # Create frame depending on Tab chosen if selected == "Register Documents": self.current_tab = RegisterChooseType(self.tab_register) self.clean_tabs() self.last_tab = self.current_tab elif selected == "Delete Documents": self.current_tab = DeleteTab(self.tab_delete) self.clean_tabs() self.last_tab = self.current_tab elif selected == "View Documents": self.current_tab = ViewTab(self.tab_view) self.clean_tabs() self.last_tab = self.current_tab self.current_tab.barcode_entry.focus() def clean_tabs(self): if self.last_tab != None: # for widget in self.last_tab.winfo_children(): # # for widget in self.last_tab.grid_slaves(): # widget.destroy() self.last_tab.destroy() # ## INTERESTING # self.last_tab.blank = ttk.Label(self.last_tab, text="1") # self.last_tab.blank.grid() # print(self.last_tab.grid_slaves()[0].cget("text")) # self.container.geometry("1x1") self.tab_parent.update() # self.container.update() # self.container.geometry("") # self.container.update() # Creatig App class App(tk.Tk): def __init__(self): super().__init__() self.geometry("") self.title("iMPETU Document Handling v.0.1.0a") self.resizable(0, 0) if __name__ == "__main__": main()
已尝试的无效方法
- 切换标签前后逐个删除当前标签页的组件
- 留空标签(理论上应为0像素,但实际导致内容下移)
- 使用
withdraw、deiconify方法 - 调用
self.container.update()更新主窗口 - 在
clean_tabs函数中先将窗口geometry设为"1x1"再改回""强制重置尺寸
内容的提问来源于stack exchange,提问作者Daniel Araújo
相关产品推荐
相关产品推荐

