Search code examples
pythonuser-interfacetkintertreeviewscrollbar

Python Tkinter Scrollbar panning upwards instead of downwards also alignment issue while using Scrollbar


I am using TKinter to build a GUI for my python application.

I want to add a scrollbar to the main screen because I have a lot of data to display but very less space. Currently I use the lines:

root=Tk()
root.state("zoomed")
#...rest of the code... (Relevant parts mentioned below:)
root.mainloop()

to take maximum advantage of available screen space but even that is not cutting it for me.

Here is John Elder(CEO of Codemy.com)'s code that I use to add a scrollbar:

# Create A Main Frame
    main_frame = Frame(root)
    main_frame.pack(fill=BOTH, expand=1)

    # Create A Canvas
    my_canvas = Canvas(main_frame)
    my_canvas.pack(side=LEFT, fill=BOTH, expand=1)

    # Add A Scrollbar To The Canvas
    my_scrollbar = ttk.Scrollbar(main_frame, orient=VERTICAL, command=my_canvas.yview)
    my_scrollbar.pack(side=RIGHT, fill=Y)

    # Configure The Canvas
    my_canvas.configure(yscrollcommand=my_scrollbar.set)
    my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion = my_canvas.bbox("all")))
    def _on_mouse_wheel(event):
        my_canvas.yview_scroll(-1 * int((event.delta / 100)), "units")

    my_canvas.bind_all("<MouseWheel>", _on_mouse_wheel)

    # Create ANOTHER Frame INSIDE the Canvas
    encompasser = Frame(my_canvas, bg=mainbg)

    # Add that New frame To a Window In The Canvas
    my_canvas.create_window((0,0), window=encompasser, anchor="n")

    #Adding the scroll bar part ends here...

    encompasser=Frame(my_canvas,bg=mainbg, borderwidth=0)
    encompasser.pack(fill=BOTH, expand=1)

    #second_frame = LabelFrame(my_canvas, borderwidth=0, bg=mainbg).pack()
    header=LabelFrame(encompasser,bg=mainbg, borderwidth=0)
    header.pack()
    greet=Label(header,font="Arial 20",text="Prescription Generator V4.0.0", bg=mainbg, fg="black").pack(pady=10)

    utilitiesF=LabelFrame(header,bg=mainbg, borderwidth=0)
    utilitiesF.pack()

    settingLF=LabelFrame(utilitiesF,bg=mainbg, borderwidth=0)

    megaF=LabelFrame(encompasser,bg=mainbg, borderwidth=0)
    megaF.pack()

    dateF=LabelFrame(utilitiesF, padx=10, pady=10, bg=mainbg, borderwidth=0)
    dateF.grid(row=0, column=1)

    date=Label(dateF,font="Arial 14",text="Date:", bg=mainbg).grid(row=0,column=0, sticky=E)
    edate=Entry(dateF, width=9,borderwidth=0, font="Arial 14")
    edate.insert(0,today)
    edate.grid(row=0, column=1, padx=5)

    my_tree_frame=LabelFrame(header, padx=10, pady=10, bg=subbg, borderwidth=0)
    my_tree_frame.pack()

Dormant scrollbar added

After Adding the scroll bar to the canvas and opening the canvas in a frame, I add things to the frame called "encompasser".

Problem: when I click on the button: Show Database, The following Treeview opens up: Treeview opens up, moving the rest of my project down

And when the rest of my project moves down, the scroll bar just does not scroll down. Scroll Bar stuck and not working on moving it up or down What am I doing wrong here? I know one solution is to open the treeview widget as a Toplevel() but I want it to be opened within the same page. Please answer my question, thank you!

One more thing: the entire alignment gets messed up when I try to pack that frame which comprises of all my widgets inside the encompasser. The whole project shifts towards the left hand side and aesthetically it does not look nice.

Showing what happened when I removed the frame called "encompasser"


Solution

  • First, you have created another frame using the same variable name encompasser:

    encompasser=Frame(my_canvas,bg=mainbg, borderwidth=0)
    encompasser.pack(fill=BOTH, expand=1)
    

    The above two lines should be removed.

    Second, you should update the scrollregion when the internal frame encompasser is resized, not my_canvas.

    Remove the line:

    my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion = my_canvas.bbox("all")))
    

    and add the below line after creating encompasser:

    encompasser.bind('<Configure>', lambda e: my_canvas.configure(scrollregion=my_canvas.bbox("all")))