Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resize Tkinter Listbox widget when window resizes

I'm new to Tkinter, and I've got a Listbox widget that I'd like to automatically-resize when changing the main window's size.

Essentially I would like to have a fluid height/width Listbox. If someone can point me to some documentation or provide a bit a code / insight, I'd appreciate it.

like image 464
garen Avatar asked Nov 30 '10 20:11

garen


2 Answers

You want to read up on the geometry managers pack and grid, which lets you place widgets in a window and specify whether they grow and shrink or not. There's a third geometry manager, place, but it's not used very often.

Here's a simple example:

import tkinter as tk

root = tk.Tk()
scrollbar = tk.Scrollbar(root, orient="vertical")
lb = tk.Listbox(root, width=50, height=20, yscrollcommand=scrollbar.set)
scrollbar.config(command=lb.yview)

scrollbar.pack(side="right", fill="y")
lb.pack(side="left",fill="both", expand=True)

for i in range(0,100):
    lb.insert("end", "item #%s" % i)

root.mainloop()

If you wish to use grid instead of pack, remove the two lines that call pack and replace them with these four lines:

root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)

scrollbar.grid(row=0, column=1, sticky="ns")
lb.grid(row=0, column=0, sticky="nsew")

Note that with grid you have to take the extra step to configure the weight for the row and column that contains the listbox, otherwise tkinter won't allocate any extra space to the widget.

like image 159
Bryan Oakley Avatar answered Sep 20 '22 20:09

Bryan Oakley


The two main ways to allow a listbox to stretch when the window is resized are using the .pack() or .grid() methods.

SPECS:

Windows 7, Python 3.8.1, tkinter version: 8.6

.pack()

I found the easiest way to do this is by using the .pack() method, and utilizing the fill= & expand=True options.

import tkinter as tk

root=tk.Tk()                                              #Creates the main window

listbox=tk.Listbox(root)                                  #Create a listbox widget

listbox.pack(padx=10,pady=10,fill=tk.BOTH,expand=True)    #fill=tk.BOTH, stretch vertically and horizontally
                                                          #fill=tk.Y, stretch vertically
                                                          #fill=tk.X, stretch horizontally

If your listbox is placed in a frame, the frame will also need to use the fill= & expand=True options.

import tkinter as tk

root=tk.Tk()

frame1=tk.Frame(root)
frame1.pack(fill=tk.BOTH, expand=True)

listbox=tk.Listbox(frame1)
listbox.pack(padx=10,pady=10,fill=tk.BOTH,expand=True)

.grid()

The alternative technique is to use the .grid() method and utilize thesticky= option. In addition, you will need to configure the row and column that the listbox resides in.

import tkinter as tk

root=tk.Tk()  #create window
root.columnconfigure(0,weight=1)    #confiugures column 0 to stretch with a scaler of 1.
root.rowconfigure(0,weight=1)       #confiugures row 0 to stretch with a scaler of 1.

listbox=tk.Listbox(root)
listbox.grid(row=0,column=0,padx=5,pady=5,sticky='nsew')   

The sticky option causes the listbox to stick to the "North" (Top), "South" (Bottom), "East" (Right), and "West" (Left) sides of the cell as it is stretched.

If your listbox is placed within a frame, you will need to configure the column and row that the frame is in, along with configure the column and row that the listbox is in.

import tkinter as tk

root=tk.Tk()               #create window
root.columnconfigure(0,weight=1)  
root.rowconfigure(0,weight=1)

frame1=tk.Frame(root)
frame1.grid(row=0,column=0,sticky='nsew')
frame1.columnconfigure(0,weight=1)
frame1.rowconfigure(0,weight=1)

listbox=tk.Listbox(frame1)
listbox.grid(row=0,column=0,padx=5,pady=5,sticky='nsew')

.pack() & .grid()

Now there is one other technique, but some people frown on it. The third technique is to utilize the .pack() method and .grid() method in the same script. You can mix different geometry management method in the same script as long as only a one management type is used per container. You can see an example of this below.

import tkinter as tk

root=tk.Tk()               #create window

frame1=tk.Frame(root)                                #container: root
frame1.pack(fill=tk.BOTH,expand=True)                               
frame1.columnconfigure(0,weight=1)
frame1.rowconfigure(0,weight=1)
frame1.rowconfigure(1,weight=1)

listbox=tk.Listbox(frame1)                            #container: frame1
listbox.grid(row=0,rowspan=2,column=0,padx=5,pady=5,sticky='nsew') 

btn1=tk.Button(frame1,text='Demo1')                   #container: frame1        
btn1.grid(row=0,column=1, padx=5, pady=5)                          

btn2=tk.Button(frame1,text='Demo2')                   #container: frame1     
btn2.grid(row=1,column=1, padx=5, pady=5)                          

frame2=tk.Frame(root)                                 #container: root 
frame2.pack()

btn3=tk.Button(frame2,text='Demo3')                   #container: frame2
btn3.grid(row=0,column=0)                                          

You can see above that the frames used .pack() while the listbox and buttons used .grid(). This was possible because the frames resided within the root container, while the listbox and buttons resided within their respective frames.


To check you tkinter version use:

import tkinter as tk
print(tk.TkVersion)

If you would like to learn about the differences between fill and expand, please see the following link. https://effbot.org/tkinterbook/pack.htm

like image 38
servant2robots Avatar answered Sep 20 '22 20:09

servant2robots