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