Tom Boddaert
Tom Boddaert

Reputation: 27

My frame is resizing instead of the listbox - tkinter

I'm making a GUI and I'm stuck trying to resize a listbox. The listbox is supposed to expand to fill the frame but instead, the frame shrinks to fit the listbox. Thanks, in advance, for any help.

I have tried many variations of the code, but none seem to work, so I simplified the code (it still does't work) to put it on here.

import tkinter as tk

w = tk.Tk() # New window

f = tk.Frame(w, width=300, height=500, bg='red') # New frame with specific size
f.grid_propagate(0)
f.grid(row=0, column=0)

lb = tk.Listbox(f, bg='blue') # New listbox
lb.pack(fill=tk.BOTH, expand=True)

I ran these sequentially in IDLE and the frame appears (in red) at the correct size, however, when I pack the listbox, the whole window shrinks to the size of the listbox (and turns completely blue, which is expected).

Upvotes: 1

Views: 833

Answers (3)

Bryan Oakley
Bryan Oakley

Reputation: 385890

In my experience, turning off geometry propagation is almost never the right solution. With a couple of decades of using tk and tkinter I've done that only two or three times for very specific edge cases.

Tkinter is very good at making the widget the best size based on the set of widgets you're using. Turning off propagation means you are responsible for doing all calculations to get the window to look right, and your calculations may not be correct when your program runs on a machine with different fonts or a different resolution. Tkinter can handle all of that for you.

Unfortunately, with such a small code example and without knowing your end goal it's hard to solve your layout problems. If your goal is to have a window that is 300x500, the best solution is to make the window that size and then have the frame fill the window, which is easier to do with pack than grid:

import tkinter as tk

w = tk.Tk() # New window
w.geometry("300x500")

f = tk.Frame(w, bg='red') # New frame with specific size
f.pack(fill="both", expand=True)

lb = tk.Listbox(f, bg='blue') # New listbox
lb.pack(fill=tk.BOTH, expand=True)

w.mainloop()

Upvotes: 1

Tls Chris
Tls Chris

Reputation: 3824

Edit: I think you actually want the listbox to expand to fit the frame. Amended the code to do that as an option

I haven't used pack much but I suspect that grid_propagate changes the behaviour of the grid geometry manager but not of the pack manager.

The below lets app() run with or without propagate set. It uses the grid geometry manager throughout.

import tkinter as tk

def app(propagate = False, expand = False ):
    w = tk.Tk() # New window

    tk.Label( w, text = 'Propagate: {} \nExpand: {}'.format(propagate, expand) ).grid()

    f = tk.Frame(w, width=300, height=500, bg='red') # New frame with specific size
    f.grid_propagate(propagate)
    f.grid( row=1, column=0 )

    lb = tk.Listbox(f, bg='blue') # New listbox
    if expand:
        f.columnconfigure(0, weight = 1 )
        f.rowconfigure(0, weight = 1 )

    # lb.pack(fill=tk.BOTH, expand=True)
    lb.grid( row=0, column=0, sticky = 'nsew' )  
    # My guess is that grid_propagate has changed the behaviour of grid, not of pack.

    lb.insert(tk.END, 'Test 1', 'Test 2', 'Test 3')

    w.mainloop()

This changes the listbox geometry manager to grid. Run app() as below.

app(True, True)   # propagate and Expand
app(False, True)  # no propagate but expand
app(True, False)  # propagate without expand
app()             # no propagate or expand

Upvotes: 0

Tom Boddaert
Tom Boddaert

Reputation: 27

Thank you so much to Tls Chris for your answer and explanation. What I didn't realize is that grid_propagate() and pack_propagate() also affect a widget's children. Therefore, with the help of Tls Chris, I have fixed my code and it now expands the listbox and doesn't shrink the frame.

Fixed code:

import tkinter as tk
w = tk.Tk() # New window

f = tk.Frame(w, width=300, height=500, bg='red') # New frame
f.grid_propagate(False) # Stopping things (that use grid) resizing the frame
f.pack_propagate(False) # Stopping things (that use pack) resizing the frame
f.grid(row=0, column=0)

lb = tk.Listbox(f, bg='blue') # New listbox
lb.pack(fill=tk.BOTH, expand=True) # Packing the listbox and making it expand and fill the frame

Upvotes: 1

Related Questions