简体   繁体   中英

How can I "reset" the size of a Window on Tkinter when using Notebook?

I know this has been asked before but none of the solutions that I've seen so far seem to work.

So here's the exact case: I'm building an app that has 3 different tabs (using ttk.Notebook). The initial contents of the 3 tabs is different: the second is the smallest and the third is he biggest.

Now here comes the issue (I'm using grid, btw): when I change from the first to the second, there is an extra empty space (because the content of the first Tab is a little bigger than the one of the second, and the same happens when I go from the third to the second/first, so after using the third tab and changing to another one, the size stays as if I still was in the third.

I add some of the code that I'm using, but since I'm not sure what is going wrong, I'll let you ask for whatever extra code you might need to help me find the solution.

# 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()

I tried deleting one by one the widgets of the current tab before changing to another one, also doing the same AFTER changing to the new tab (that's why I have 2 variables for current and last tab), I also tried leaving an empty tag (supposedly 0 pixels) but that would push all the contents down.

I tried withdraw, deiconify just out of curiosity, I also tried using self.container.update() to update the main window, also tried changing the geometry to "1x1" in the clean_tabs function and then changing again to "" at the end of the on_tab_change and see if that would maybe force it to resize but none of that worked.

You can resize all the frames (parents of instances of RegisterChooseType , DeleteTab and ViewTab ) to size 1x1 at the beginning of clean_tabs() :

def clean_tabs(self):
    for tab in self.tab_parent.tabs():
        # tab is the name of the frame
        # so get the widget using .nametowidget()
        # then call .config(width=1, height=1) to resize the frame to size 1x1
        self.tab_parent.nametowidget(tab).config(width=1, height=1)
    ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM