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.
CodePudding user response:
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)
...