Search code examples
pythontkinterscrollbar

Using 2 scrollbars tkinter


I would like to add 2 scrollbars to a tkinter window.

Here's what I managed to get:

from tkinter import *
from tkinter import ttk

options = ["A", "B", "C", "D", "E", "F", "G", "H"]

root = Tk()

root.title("random software")

content = ttk.Frame(root)
content.pack(fill=BOTH, expand=1);

scrollable_canvas = Canvas(content)
scrollable_canvas.pack(side=LEFT, fill=BOTH, expand=1)

vscrollbar = ttk.Scrollbar(content, orient=VERTICAL, command=scrollable_canvas.yview)
vscrollbar.pack(side=RIGHT, fill=Y)

hscrollbar = ttk.Scrollbar(content, orient=HORIZONTAL, command=scrollable_canvas.xview)
hscrollbar.pack(side=BOTTOM, fill=X)

scrollable_canvas.configure(yscrollcommand=vscrollbar.set)
scrollable_canvas.configure(xscrollcommand=hscrollbar.set)
scrollable_canvas.bind('<Configure>', lambda e: scrollable_canvas.configure(scrollregion = scrollable_canvas.bbox("all")))

inner_frame = Frame(scrollable_canvas)

scrollable_canvas.create_window((0, 0), window=inner_frame, anchor="nw")
if hscrollbar:
    print("hey")

A_label = Label(inner_frame, text = "A")
A_entry = Entry(inner_frame, width = 5)
A_hint = Label(inner_frame, text = "lorem")
A_hint2 = Label(inner_frame, text = "lorem")
A_hint3 = Label(inner_frame, text = "lorem")
A_hint4 = Label(inner_frame, text = "lorem")
A_hint5 = Label(inner_frame, text = "lorem")

B_label = Label(inner_frame, text = "B")
B_entry = Entry(inner_frame, width = 5)
B_hint = Label(inner_frame, text = "ipsum")

C_label = Label(inner_frame, text = "C")
C_entry = Entry(inner_frame, width = 5)
C_hint = Label(inner_frame, text = "dolor")

D_label = Label(inner_frame, text = "D")
D_entry = Entry(inner_frame, width = 5)
D_hint = Label(inner_frame, text = "sit")

E_label = Label(inner_frame, text = "E")
E_entry = Entry(inner_frame, width = 5)
E_hint = Label(inner_frame, text = "amet")

F_label = Label(inner_frame, text = "F")
F_entry = Entry(inner_frame, width = 5)
F_hint = Label(inner_frame, text = "consectetur")

G_label = Label(inner_frame, text = "G")
G_entry = Entry(inner_frame, width = 5)
G_hint = Label(inner_frame, text = "adipiscing")

H_label = Label(inner_frame, text = "H")
H_entry = Entry(inner_frame, width = 5)
H_hint = Label(inner_frame, text = "elit")

A_label.grid(row = 6, column = 0)
A_entry.grid(row = 6, column = 1)
A_hint.grid(row = 6, column = 3, sticky = "w")
A_hint2.grid(row = 6, column = 4, sticky = "w")
A_hint3.grid(row = 6, column = 5, sticky = "w")
A_hint4.grid(row = 6, column = 6, sticky = "w")
A_hint5.grid(row = 6, column = 7, sticky = "w")

B_label.grid(row = 7, column = 0)
B_entry.grid(row = 7, column = 1)
B_hint.grid(row = 7, column = 3, sticky = "w")

C_label.grid(row = 8, column = 0)
C_entry.grid(row = 8, column = 1)
C_hint.grid(row = 8, column = 3, sticky = "w")

D_label.grid(row = 9, column = 0)
D_entry.grid(row = 9, column = 1)
D_hint.grid(row = 9, column = 3, sticky = "w", columnspan = 2)

E_label.grid(row = 10, column = 0)
E_entry.grid(row = 10, column = 1)
E_hint.grid(row = 10, column = 3, sticky = "w")

F_label.grid(row = 11, column = 0)
F_entry.grid(row = 11, column = 1)
F_hint.grid(row = 11, column = 3, sticky = "w")

G_label.grid(row = 12, column = 0)
G_entry.grid(row = 12, column = 1)
G_hint.grid(row = 12, column = 3, sticky = "w")

H_label.grid(row = 13, column = 0)
H_entry.grid(row = 13, column = 1)
H_hint.grid(row = 13, column = 3, sticky = "w")



root.mainloop()

I guess it's a problem with pack but I don't know how to solve it. By default, pack packs the current widget at the top and I guess I would need it to pack the inner_frame to the top left. Since it doesn't allow 2 arguments for the orientation or center as orientation, what is wrong?

Thanks in advance


Solution

  • Thanks to acw1668, I managed to solve the problem using grid:

    from tkinter import *
    from tkinter import ttk
    
    options = ["A", "B", "C", "D", "E", "F", "G", "H"]
    
    root = Tk()
    
    root.title("random software")
    
    content = ttk.Frame(root)
    content.grid_rowconfigure(0, weight = 1)
    content.grid_columnconfigure(0, weight = 1)
    
    scrollable_canvas = Canvas(content)
    
    vscrollbar = ttk.Scrollbar(content, orient=VERTICAL, command=scrollable_canvas.yview)
    
    hscrollbar = ttk.Scrollbar(content, orient=HORIZONTAL, command=scrollable_canvas.xview)
    
    scrollable_canvas.configure(yscrollcommand=vscrollbar.set)
    scrollable_canvas.configure(xscrollcommand=hscrollbar.set)
    scrollable_canvas.bind('<Configure>', lambda e: scrollable_canvas.configure(scrollregion = scrollable_canvas.bbox("all")))
    
    inner_frame = Frame(scrollable_canvas)
    
    scrollable_canvas.create_window((0, 0), window=inner_frame, anchor="nw")
    if hscrollbar:
        print("hey")
    
    A_label = Label(inner_frame, text = "A")
    A_entry = Entry(inner_frame, width = 5)
    A_hint = Label(inner_frame, text = "lorem")
    A_hint2 = Label(inner_frame, text = "lorem")
    A_hint3 = Label(inner_frame, text = "lorem")
    A_hint4 = Label(inner_frame, text = "lorem")
    A_hint5 = Label(inner_frame, text = "lorem")
    
    B_label = Label(inner_frame, text = "B")
    B_entry = Entry(inner_frame, width = 5)
    B_hint = Label(inner_frame, text = "ipsum")
    
    C_label = Label(inner_frame, text = "C")
    C_entry = Entry(inner_frame, width = 5)
    C_hint = Label(inner_frame, text = "dolor")
    
    D_label = Label(inner_frame, text = "D")
    D_entry = Entry(inner_frame, width = 5)
    D_hint = Label(inner_frame, text = "sit")
    
    E_label = Label(inner_frame, text = "E")
    E_entry = Entry(inner_frame, width = 5)
    E_hint = Label(inner_frame, text = "amet")
    
    F_label = Label(inner_frame, text = "F")
    F_entry = Entry(inner_frame, width = 5)
    F_hint = Label(inner_frame, text = "consectetur")
    
    G_label = Label(inner_frame, text = "G")
    G_entry = Entry(inner_frame, width = 5)
    G_hint = Label(inner_frame, text = "adipiscing")
    
    H_label = Label(inner_frame, text = "H")
    H_entry = Entry(inner_frame, width = 5)
    H_hint = Label(inner_frame, text = "elit")
    
    content.pack(fill=BOTH, expand=1);
    
    scrollable_canvas.grid(row = 0, column = 0, sticky = "nsew")
    vscrollbar.grid(row = 0, column = 1, sticky = "ns")
    hscrollbar.grid(row = 1, column = 0, sticky = "ew")
    
    A_label.grid(row = 6, column = 0)
    A_entry.grid(row = 6, column = 1)
    A_hint.grid(row = 6, column = 3, sticky = "w")
    A_hint2.grid(row = 6, column = 4, sticky = "w")
    A_hint3.grid(row = 6, column = 5, sticky = "w")
    A_hint4.grid(row = 6, column = 6, sticky = "w")
    A_hint5.grid(row = 6, column = 7, sticky = "w")
    
    B_label.grid(row = 7, column = 0)
    B_entry.grid(row = 7, column = 1)
    B_hint.grid(row = 7, column = 3, sticky = "w")
    
    C_label.grid(row = 8, column = 0)
    C_entry.grid(row = 8, column = 1)
    C_hint.grid(row = 8, column = 3, sticky = "w")
    
    D_label.grid(row = 9, column = 0)
    D_entry.grid(row = 9, column = 1)
    D_hint.grid(row = 9, column = 3, sticky = "w", columnspan = 2)
    
    E_label.grid(row = 10, column = 0)
    E_entry.grid(row = 10, column = 1)
    E_hint.grid(row = 10, column = 3, sticky = "w")
    
    F_label.grid(row = 11, column = 0)
    F_entry.grid(row = 11, column = 1)
    F_hint.grid(row = 11, column = 3, sticky = "w")
    
    G_label.grid(row = 12, column = 0)
    G_entry.grid(row = 12, column = 1)
    G_hint.grid(row = 12, column = 3, sticky = "w")
    
    H_label.grid(row = 13, column = 0)
    H_entry.grid(row = 13, column = 1)
    H_hint.grid(row = 13, column = 3, sticky = "w")
    
    
    
    root.mainloop()
    

    The grid_rowconfigure and grid_columnconfigure methods with non-null weights make sure that extra space is allocated to the scrollbars.