How can I access the scroll_frame outside the function so that the new_frame will be inside the scroll_frame in the code below.
def scroll():
container = LabelFrame(root)
my_canvas = Canvas(container)
my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
scroll_y = Scrollbar(container, orient=VERTICAL, command=my_canvas.yview)
scroll_y.pack(side=RIGHT, fill='y')
my_canvas.configure(yscrollcommand=scroll_y.set)
my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion=my_canvas.bbox('all')))
scroll_frame = Frame(my_canvas)
my_canvas.create_window((0, 0), window=scroll_frame, anchor=NW)
container.pack(fill=BOTH, expand=1)
new_frame = Frame(scroll_frame)
for i in range(25):
Button(new_frame, text='click'+str(i)).pack()
scroll()
root.mainloop()
If you want to access scroll_frame
, you should return it from scroll()
.
Suggest to return container
as well and don't call container.pack(...)
inside scroll()
because it is more flexible.
Also suggest to pass the parent to scroll()
as well instead of hard-coded root
inside it.
from tkinter import *
def scroll(parent):
container = LabelFrame(parent)
my_canvas = Canvas(container, highlightthickness=0)
my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
scroll_y = Scrollbar(container, orient=VERTICAL, command=my_canvas.yview)
scroll_y.pack(side=RIGHT, fill=Y)
my_canvas.configure(yscrollcommand=scroll_y.set)
scroll_frame = Frame(my_canvas)
my_canvas.create_window((0, 0), window=scroll_frame, anchor=NW)
# bind <Configure> on scroll_frame instead of my_canvas
scroll_frame.bind('<Configure>', lambda e: my_canvas.configure(scrollregion=my_canvas.bbox('all')))
return container, scroll_frame
root = Tk()
container, scroll_frame = scroll(root)
container.pack(fill=BOTH, expand=1)
# Is new_frame necessary? Why not use scroll_frame directly?
new_frame = Frame(scroll_frame)
new_frame.pack()
for i in range(25):
Button(new_frame, text='click'+str(i)).pack(fill=X)
root.mainloop()
Note that if you want to use scroll()
repeatedly, better use class instead of function.
Update: using class implemenatation:
import tkinter as tk
class ScrollableFrame(tk.LabelFrame):
def __init__(self, parent, **kw):
super().__init__(parent, **kw)
canvas = tk.Canvas(self, highlightthickness=0)
canvas.pack(side="left", fill="both", expand=1)
vscrollbar = tk.Scrollbar(self, orient="vertical", command=canvas.yview)
vscrollbar.pack(side="right", fill="y")
canvas.config(yscrollcommand=vscrollbar.set)
self.scroll_frame = tk.Frame(canvas)
self.scroll_frame.bind("<Configure>", lambda e: canvas.config(scrollregion=canvas.bbox("all")))
canvas.create_window(0, 0, window=self.scroll_frame, anchor="nw")
if __name__ == "__main__":
root = tk.Tk()
container = ScrollableFrame(root)
container.pack(fill="both", expand=1)
for i in range(25):
tk.Button(container.scroll_frame, text=f"click {i}").pack(fill="x")
root.mainloop()