pythontkinterscrollable

Scrollable cards in tkinter


So I am trying to create a landing with cards describing a problem. For this, I create a frame that will act as the card for my text and images to be displayed on. My main issue is to be able to make the whole main_canvas scrollable which I tried but it simply doesn't work. first came the issue of when I packed it in the canvas the whole canvas shrinks to the size of the scrollbar which I fixed by creating a new frame for the scrollbar then a persistent problem appeared of the scrollbar not working.

from tkinter import *

def close_win(e):
   main_window.destroy()
main_window = Tk()

main_window.attributes('-fullscreen',True)
main_window.config(bg="#1b2036")
main_canvas = Canvas(
    main_window,
    bg='red',
    height= 715,
    width=1300,
    bd=0,
    highlightthickness=0,
    relief='ridge',
)
scroll_bar_frame=Frame(main_canvas,height=715,bg="white")


frame_12= Frame(
    
    main_canvas,
    bg="white",
    relief="sunken",
    borderwidth=0,
    width=100,
    height=200
)
mls_descript2=Label(
    frame_12,
    text='Multilevel Search is a 2D data \nstructure in which each node \nhas a next and child pointer.',
    background="#1b2036",
    border=0,
    font=('Poppins Bold',18*-1),
    fg="white",
    justify=LEFT
)
main_canvas.pack()
main_canvas.create_window(0,0, window=frame_12,anchor="nw")
#main_canvas.create_window(1280,357,window=scroll_bar_frame,anchor="e")
vbar=Scrollbar(main_window,orient=VERTICAL)
vbar.pack(side=RIGHT,fill = Y)
main_canvas.config(yscrollcommand=vbar.set)
vbar.config(command=main_canvas.yview)
for i in range(100):
    frame_13= Frame(
    frame_12,
    bg="yellow",
    relief="sunken",
    borderwidth=0,
    width=100,
    height=200
    )  
    frame_13.pack(padx=5,pady=5)

main_window.bind('<Escape>', lambda e: close_win(e))
main_window.mainloop()

When I created a new frame for the scrollbar it appeared to be right and I was expecting that the scrollbar should work I tried everything, playing around with where the scrollbar was packed blah blah but to no avail.


Solution

  • You have forgot to set the scrollregion option of main_canvas. Normally it should be updated whenever the internal frame frame_12 is resized:

    # update scrollregion of canvas whenever frame_12 is resized
    frame_12.bind("<Configure>", lambda e: main_canvas.config(scrollregion=main_canvas.bbox("all")))
    

    Also you need to pack main_canvas to the left side and fill the available space:

    main_canvas.pack(side=LEFT, fill=BOTH, expand=1)