Tkinter Grid: How to make entry fill the entire row and be responsive to window resizing?

Question:

Tkinter Grid: How to make entry fill the entire row and be responsive to window resizing?

In a custom widget, how to make the entry occupy the entire length of the column?
see the example below, I need the second entry(self.ent_txt) of my custom widget to occupy the entire width of the frame

import tkinter as tk
from tkinter import ttk

class MyCustomWidget(ttk.Frame):
    def __init__(self, master, title=None, *args, **kwargs):
        super().__init__( master, *args, **kwargs)

        self.title = title

        self.buid_widgets()
        return
    
    def buid_widgets(self):
        self.main_frm = ttk.Frame(self)
        self.main_frm.grid(row=0, column=0, sticky=tk.NSEW)
        
        idx_column = -1
        if self.title is not None:
            idx_column += 1
            ttk.Label(self.main_frm, text=self.title).grid(row=0, column=idx_column)
            self.main_frm.columnconfigure((0,1,2), weight=1)
            self.main_frm.columnconfigure(3, weight=7)
        else:
            self.main_frm.columnconfigure((0,1), weight=1)
            self.main_frm.columnconfigure(2, weight=8)

        self.ent_cod = ttk.Entry(self.main_frm, width=10)
        self.ent_cod.grid(row=0, column=idx_column+1)

        self.btn_show_dt = ttk.Button(self.main_frm, text='OK')
        self.btn_show_dt.grid(row=0, column=idx_column+2)

        self.ent_txt = ttk.Entry(self.main_frm)
        self.ent_txt.grid(row=0, column=idx_column+3, sticky=tk.EW)

        self.main_frm.columnconfigure(idx_column+3, weight=10)
        
        return


if __name__== '__main__':
    app = tk.Tk()
    app.geometry('600x200')

    s = ttk.Style()
    s.configure('new.TFrame', background='#7AC5CD')

    frm_main = ttk.Frame(app, style='new.TFrame')
    frm_main.pack(fill=tk.BOTH, expand=1)

    frm_container = ttk.Frame(frm_main)
    frm_container.grid(row=0, column=0, sticky=tk.NSEW)
    frm_container.columnconfigure(0, weight=1)
    frm_container.columnconfigure(1, weight=100)

    ttk.Label(frm_container, text='Test0:').grid(row=0, column=0)
    ttk.Entry(frm_container).grid(row=0, column=1, sticky=tk.EW)

    wd_custom = MyCustomWidget(frm_container, title='Test1:')
    wd_custom.grid(row=1, column=0, columnspan=2, sticky=tk.EW)

    tk.Text(frm_container).grid(row=2, column=0, columnspan=2)
    app.mainloop()

enter image description here

Asked By: Mrkalvin Bs

||

Answers:

A good rule of thumb is to always give at least one row and one column a weight greater than zero for every widget that uses grid to manage child widgets.

Another helpful tip is that if a widget has only a single child, it’s easier to use pack rather than grid since you can make it responsive all in a single line of code.

So, with that I recommend you use pack rather than grid for frm_container in the main block of code so that the container fills the window it is in.

frm_container.pack(fill="both", expand=True)

The same can be done inside of MyCustomWidget for main_frm since it’s the only widget directly in self.

self.main_frm.pack(fill="both", expand=True)

If you prefer using grid inside of MyCustomWidget then you need to follow that first rule of thumb and give a weight to the row and column that contains the entry widget.

self.main_frm = ttk.Frame(self)
self.main_frm.grid(row=0, column=0, sticky=tk.NSEW)
self.grid_columnconfigure(0, weight=1)
self.grid_rowconfigure(0, weight=1)
Answered By: Bryan Oakley

@Bryan Oakley

Thanks for the tips.
I created the custom widget using pack.
And in the app I used the grid to build the interface. and it worked. see the result after the suggested modifications:

import tkinter as tk
from tkinter import ttk

class MyCustomWidget(ttk.Frame):
    def __init__(self, master, title=None, *args, **kwargs):
        super().__init__( master, *args, **kwargs)

        self.title = title

        self.buid_widgets()
        return
    
    def buid_widgets(self):
        self.main_frm = ttk.Frame(self)
        self.main_frm.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
        
        if self.title is not None:
            ttk.Label(self.main_frm, text=self.title).pack(side=tk.LEFT)

        self.ent_cod = ttk.Entry(self.main_frm, width=10)
        self.ent_cod.pack(side=tk.LEFT, fill=tk.Y)

        self.btn_show_dt = ttk.Button(self.main_frm, text='OK')
        self.btn_show_dt.pack(side=tk.LEFT)

        self.ent_txt = ttk.Entry(self.main_frm)
        self.ent_txt.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
        return


if __name__== '__main__':
    app = tk.Tk()
    app.geometry('600x200')

    s = ttk.Style()
    s.configure('new.TFrame', background='#7AC5CD')

    frm_main = ttk.Frame(app, style='new.TFrame')
    frm_main.pack(fill=tk.BOTH, expand=1)
    frm_main.grid_columnconfigure(0, weight=1)
    frm_main.grid_rowconfigure(0, weight=1)

    frm_container = ttk.Frame(frm_main)
    frm_container.grid(row=0, column=0, sticky=tk.NSEW)
    frm_container.columnconfigure(0, weight=1)
    frm_container.columnconfigure(1, weight=100)

    ttk.Label(frm_container, text='Test0:').grid(row=0, column=0)
    ttk.Entry(frm_container).grid(row=0, column=1, sticky=tk.EW)

    wd_custom = MyCustomWidget(frm_container, title='Test1:')
    wd_custom.grid(row=1, column=0, columnspan=2, sticky=tk.EW)

    tk.Text(frm_container).grid(row=2, column=0, columnspan=2, sticky=tk.NSEW)
    app.mainloop()
Answered By: Mrkalvin Bs
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.