You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 21:35:22