Search code examples
pythontkinterbuttonlistboxscrollbar

How can I use the scrollbar to scroll vertically through the buttons in the list?


I need the buttons in the types list to scroll vertically using the scrollbar, but something is wrong with my code below. This is because the scrollbar works but the buttons in the list do not scroll using the scrollbar. I tried putting numbers in the types list and that works very well, so why can't I put a list of buttons there and make them scroll?

import tkinter as tk
from tkinter import ttk

window = tk.Tk()
window.geometry('100x50')
window.minsize(10,5)

types = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]

tscroll = tk.Scrollbar(window)

lb = tk.Listbox(window,bg = 'silver' )

tscroll.pack(side='left',fill='y')

lb.pack(side = 'left',fill = 'both')

def type1details():
    pass

count = 0
for t in types:
    button = ttk.Button(lb, text = t,command=type1details)
    lb.insert(count,button)
    button.pack()
    count += 1
lb.config(yscrollcommand = tscroll.set)
tscroll.config(command=lb.yview)

window.mainloop()

Solution

  • listbox widget can only display strings so with this you can't display widgets like buttons, if you use canvas instead of listbox you can achieve your goal:

    import tkinter as tk
    from tkinter import ttk
    
    window = tk.Tk()
    window.geometry('100x150')
    window.minsize(10, 5)
    
    types = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
    
    canvas = tk.Canvas(window, bg='silver', width=100, height=150, 
    highlightthickness=0)
    scrollbar = tk.Scrollbar(window, orient='vertical', command=canvas.yview)
    
    frame = tk.Frame(canvas, bg='silver')
    frame.bind('<Configure>', lambda e: 
    canvas.configure(scrollregion=canvas.bbox('all')))
    canvas.create_window((0, 0), window=frame, anchor='nw')
    canvas.configure(yscrollcommand=scrollbar.set)
    
    scrollbar.pack(side='right', fill='y')
    canvas.pack(side='left', fill='both', expand=True)
    
    def type1details():
          pass
    
    for t in types:
    button = ttk.Button(frame, text=t, command=type1details)
    button.pack()
    
    window.mainloop()