tkinter Label frame and its widgets not getting resized

78 Views Asked by At

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

1

There are 1 best solutions below

2
furas On BEST ANSWER

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