pythontkinterwindow-resize

tkinter Label frame and its widgets not getting resized


I am creating a custom tkinter class ResizableLabelFrame() which has a label frame and an inner frame to hold widgets. While resizing the window, the widgets are not getting resized. Could anyone point me in the right direction solving this issue? Thanks in advance. Most of the time I was able to solve the issues just by reading the questions and answers posted in Stack Overflow and my learning advanced a lot with your help. Thank you so much.
full window reduced window

I tried columnconfigure(0, weight=1), rowconfigure(0, weight=1) I want to create a custom label frame class which resizes its inner frames and widgets

from tkinter import *
class ResizableLabelFrame(LabelFrame):
    def __init__(self, master=None, **kwargs):
        LabelFrame.__init__(self, master, **kwargs)

        # Set default weight for resizing
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        # Bind the resizing function to the label frame
        self.bind("<Configure>", self.on_resize)

        # Create a frame inside the LabelFrame to hold widgets
        self.inner_frame = Frame(self)
        self.inner_frame.grid(row=0, column=0, sticky="nsew")
        self.inner_frame.columnconfigure(0, weight=1)
        self.inner_frame.rowconfigure(0, weight=1)
        resizable_frame_inner_frame_columns = self.inner_frame.grid_size()[0] 
        print(resizable_frame_inner_frame_columns)
        """
        for i in range(resizable_frame_inner_frame_columns):
            resizable_frame.columnconfigure(i, weight=1)
        """
    def on_resize(self, event):
        # Get the new size of the label frame
        width = event.width
        height = event.height
        print(width,"X",height)

        # Resize the inner frame to match the label frame's size
        self.inner_frame.config(width=width, height=height)

        # Resize widgets inside the inner frame if needed
        for widget in self.inner_frame.winfo_children():
            self.resize_widget(widget)

    def resize_widget(self, widget):
        # Resize the widget if it has a resize method
        if hasattr(widget, "resize"):
            widget.resize()

    def add_widget(self, widget, position):
        # Add a widget to the inner frame
        widget.grid(row=0, column=position, padx=10, pady=10, sticky="nsew")


if __name__ == "__main__":
    root = Tk()
    root.geometry("500x100")

    # Create an instance of ResizableLabelFrame
    resizable_frame = ResizableLabelFrame(root, text="Controls")
    resizable_frame.grid(row=0, column=0, sticky="nsew")

    # Add widgets to the resizable frame
    label = Label(resizable_frame.inner_frame, text="Enter TOTP")
    entry = Entry(resizable_frame.inner_frame)
    button = Button(resizable_frame.inner_frame, text="Connect")
    
    resizable_frame.add_widget(label, 0)
    resizable_frame.add_widget(entry, 1)
    resizable_frame.add_widget(button, 2)
    resizable_frame_columns = resizable_frame.grid_size()[0] 
    print(resizable_frame_columns)
    
    # Example of a widget with a custom resize method
    class CustomResizableWidget(Label):
        def resize(self):
            # Custom resizing logic for the widget
            pass

    custom_widget = CustomResizableWidget(resizable_frame.inner_frame, text="Connection Status")
    resizable_frame.add_widget(custom_widget, 3)

    root.mainloop()


Solution

  • It resizes frame when I add

    root.columnconfigure(0, weight=1)
    root.rowconfigure(0, weight=1)
    

    or when I remove grid() and use pack()

    resizable_frame.pack(fill='both', expand=True)
    

    Tested on Linux Mint, Python 3.10

    To make sure I put full working code after image. And I add comments # <-- HERE in code.

    enter image description here

    enter image description here

    from tkinter import *
    
    class ResizableLabelFrame(LabelFrame):
    
        def __init__(self, master=None, **kwargs):
            LabelFrame.__init__(self, master, **kwargs)
    
            # Set default weight for resizing
            self.columnconfigure(0, weight=1)
            self.rowconfigure(0, weight=1)
    
            # Bind the resizing function to the label frame
            self.bind("<Configure>", self.on_resize)
    
            # Create a frame inside the LabelFrame to hold widgets
            self.inner_frame = Frame(self)
            self.inner_frame.grid(row=0, column=0, sticky="nsew")
            self.inner_frame.columnconfigure(0, weight=1)
            self.inner_frame.rowconfigure(0, weight=1)
            resizable_frame_inner_frame_columns = self.inner_frame.grid_size()[0] 
            print(resizable_frame_inner_frame_columns)
            """
            for i in range(resizable_frame_inner_frame_columns):
                resizable_frame.columnconfigure(i, weight=1)
            """
        def on_resize(self, event):
            # Get the new size of the label frame
            width = event.width
            height = event.height
            print(width,"X",height)
    
            # Resize the inner frame to match the label frame's size
            self.inner_frame.config(width=width, height=height)
    
            # Resize widgets inside the inner frame if needed
            for widget in self.inner_frame.winfo_children():
                self.resize_widget(widget)
    
        def resize_widget(self, widget):
            # Resize the widget if it has a resize method
            if hasattr(widget, "resize"):
                widget.resize()
    
        def add_widget(self, widget, position):
            # Add a widget to the inner frame
            widget.grid(row=0, column=position, padx=10, pady=10, sticky="nsew")
    
    
    if __name__ == "__main__":
        root = Tk()
        root.geometry("500x100")
    
        # Create an instance of ResizableLabelFrame
        resizable_frame = ResizableLabelFrame(root, text="Controls")
        
        # --- version 1 ---
        #resizable_frame.grid(row=0, column=0, sticky="nsew")
        #root.columnconfigure(0, weight=1)  # <-- HERE
        #root.rowconfigure(0, weight=1)     # <-- HERE
    
        # --- version 2 ---
        resizable_frame.pack(fill='both', expand=True)    # <-- HERE
    
        # Add widgets to the resizable frame
        label = Label(resizable_frame.inner_frame, text="Enter TOTP")
        entry = Entry(resizable_frame.inner_frame)
        button = Button(resizable_frame.inner_frame, text="Connect")
        
        resizable_frame.add_widget(label, 0)
        resizable_frame.add_widget(entry, 1)
        resizable_frame.add_widget(button, 2)
        resizable_frame_columns = resizable_frame.grid_size()[0] 
        print(resizable_frame_columns)
        
        # Example of a widget with a custom resize method
        class CustomResizableWidget(Label):
            def resize(self):
                # Custom resizing logic for the widget
                pass
    
        custom_widget = CustomResizableWidget(resizable_frame.inner_frame, text="Connection Status")
        resizable_frame.add_widget(custom_widget, 3)
    
        root.mainloop()