0

I've looked at a number of references both on stackoverflow and other places (effbot, etc.). I've been able to get the frame on a canvas with the scrollbars showing but can't get it to scroll. enter image description here

In this example I want the frame with the Entry widgets to scroll. I have another (real) application that has a large number of entry widgets which causes the frame to exceed the height of its parent.

#  **** SCROLL BAR TEST *****
from tkinter import *
from tkinter import ttk

root = Tk()
root.title("Scrollbar Test")
root.geometry("800x400")
root.configure(background="light gray")

frame = Frame(root, height=300, width = 200, borderwidth=2, relief=SUNKEN, background="light gray")
frame.grid(column=0, row=0, sticky=W)


yscrollbar = Scrollbar(frame)
yscrollbar.grid(column=1, row=2, sticky=N+S)


canvas = Canvas(frame, bd=0, scrollregion=(0,0,800, 600), yscrollcommand=yscrollbar.set)
canvas.grid(column=0, row=0, sticky=N+S+E+W)

yscrollbar.config(command=canvas.yview)

frame = Frame(canvas, height=300, width = 200, borderwidth=2, relief=SUNKEN, background="light gray")
frame.grid(column=0, row=0, sticky=W)

label = ttk.Label(frame, text="This is a label")
label.grid(column=1, row=0, sticky=W)

text = ttk.Entry(frame, textvariable="text")
text.grid(column=2, row=0, sticky=W)


label1= ttk.Label(frame, text="This is a label")
label1.grid(column=1, row=1, sticky=W)

text1 = ttk.Entry(frame, textvariable="text")
text1.grid(column=2, row=1, sticky=W)

label2 = ttk.Label(frame, text="This is a label")
label2.grid(column=1, row=2, sticky=W)

text2 = ttk.Entry(frame, textvariable="text")
text2.grid(column=2, row=2, sticky=W)

label3 = ttk.Label(frame, text="This is a label")
label3.grid(column=1, row=3, sticky=W)

text3 = ttk.Entry(frame, textvariable="text")
text3.grid(column=2, row=3, sticky=W)

label4 = ttk.Label(frame, text="This is a label")
label4.grid(column=1, row=4, sticky=W)

text4 = ttk.Entry(frame, textvariable="text")
text4.grid(column=2, row=4, sticky=W)

label5 = ttk.Label(frame, text="This is a label")
label5.grid(column=1, row=5, sticky=W)

text5 = ttk.Entry(frame, textvariable="text")
text5.grid(column=2, row=5, sticky=W)

label6 = ttk.Label(frame, text="This is a label")
label6.grid(column=1, row=6, sticky=W)

text6 = ttk.Entry(frame, textvariable="text")
text6.grid(column=2, row=6, sticky=W)

label7 = ttk.Label(frame, text="This is a label")
label7.grid(column=1, row=7, sticky=W)

text7 = ttk.Entry(frame, textvariable="text")
text7.grid(column=2, row=7, sticky=W)

label8 = ttk.Label(frame, text="This is a label")
label8.grid(column=1, row=8, sticky=W)

text8 = ttk.Entry(frame, textvariable="text")
text8.grid(column=2, row=8, sticky=W)

label9 = ttk.Label(frame, text="This is a label")
label9.grid(column=1, row=9, sticky=W)


text9 = ttk.Entry(frame, textvariable="text")
text9.grid(column=2, row=9, sticky=W)



root.mainloop()
Thomas Smyth - Treliant
  • 4,993
  • 6
  • 25
  • 36
Seanmc2
  • 67
  • 1
  • 6
  • You can't scroll things added to a canvas with `pack`, `place`, or `grid`. Read https://stackoverflow.com/a/3092341/7432 for an example – Bryan Oakley Dec 29 '17 at 19:13

1 Answers1

0

First, the scrollbar should be placed on the same row as the canvas.

Second, setting the height and width of a Frame is pointless since those are overridden by the sizes of the child attributes.

Third, items are added to a Canvas with the create_window method, not grid().

Forth, instead of setting the scrollregion, you need to add a function that updates it based on the frame size.

All together:

#  **** SCROLL BAR TEST *****
from tkinter import *
from tkinter import ttk

def _on_frame_configure(self, event=None):
    canvas.configure(scrollregion=canvas.bbox("all"))

root = Tk()
root.title("Scrollbar Test")
root.geometry("800x400")
root.configure(background="light gray")

frame = Frame(root, borderwidth=2, relief=SUNKEN, background="light gray")
frame.grid(column=0, row=0, sticky=N+S+E+W)


yscrollbar = Scrollbar(frame)
yscrollbar.grid(column=1, row=0, sticky=N+S)

canvas = Canvas(frame, bd=0, yscrollcommand=yscrollbar.set)
canvas.grid(column=0, row=0, sticky=N+S+E+W)

yscrollbar.config(command=canvas.yview)

frame = Frame(canvas, borderwidth=2, relief=SUNKEN, background="light gray")
canvas.create_window(4, 4, window=frame, anchor='nw')
frame.bind("<Configure>", _on_frame_configure)

for i in range(30):
    label = ttk.Label(frame, text="This is a label "+str(i))
    label.grid(column=1, row=i, sticky=W)

    text = ttk.Entry(frame, textvariable="text")
    text.grid(column=2, row=i, sticky=W)

root.mainloop()

Or just use a scrolled frame that someone has already made, like this one that I made awhile ago.

Novel
  • 13,406
  • 2
  • 25
  • 41