Skip to content

Instantly share code, notes, and snippets.

@secemp9
Created August 23, 2022 20:54
Show Gist options
  • Save secemp9/f3f294f90b96345df006272d7c93bfe0 to your computer and use it in GitHub Desktop.
Save secemp9/f3f294f90b96345df006272d7c93bfe0 to your computer and use it in GitHub Desktop.
import tkinter as tk
import platform
# ************************
# Scrollable Frame Class
# ************************
class ScrollFrame(tk.Frame):
def __init__(self, parent):
super().__init__(parent) # create a frame (self)
self.canvas = tk.Canvas(self, borderwidth=0, background="#ffffff") # place canvas on self
self.viewPort = tk.Frame(self.canvas,
background="#ffffff") # place a frame on the canvas, this frame will hold the child widgets
self.vsb = tk.Scrollbar(self, orient="vertical", command=self.canvas.yview) # place a scrollbar on self
self.canvas.configure(yscrollcommand=self.vsb.set) # attach scrollbar action to scroll of canvas
self.vsb.pack(side="right", fill="y") # pack scrollbar to right of self
self.canvas.pack(side="left", fill="both", expand=True) # pack canvas to left of self and expand to fil
self.canvas_window = self.canvas.create_window((4, 4), window=self.viewPort, anchor="nw",
# add view port frame to canvas
tags="self.viewPort")
self.viewPort.bind("<Configure>",
self.onFrameConfigure) # bind an event whenever the size of the viewPort frame changes.
self.canvas.bind("<Configure>",
self.onCanvasConfigure) # bind an event whenever the size of the canvas frame changes.
self.viewPort.bind('<Enter>', self.onEnter) # bind wheel events when the cursor enters the control
self.viewPort.bind('<Leave>', self.onLeave) # unbind wheel events when the cursorl leaves the control
self.onFrameConfigure(
None) # perform an initial stretch on render, otherwise the scroll region has a tiny border until the first resize
def onFrameConfigure(self, event):
'''Reset the scroll region to encompass the inner frame'''
self.canvas.configure(scrollregion=self.canvas.bbox(
"all")) # whenever the size of the frame changes, alter the scroll region respectively.
def onCanvasConfigure(self, event):
'''Reset the canvas window to encompass inner frame when required'''
canvas_width = event.width
self.canvas.itemconfig(self.canvas_window,
width=canvas_width) # whenever the size of the canvas changes alter the window region respectively.
def onMouseWheel(self, event): # cross platform scroll wheel event
if platform.system() == 'Windows':
self.canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
elif platform.system() == 'Darwin':
self.canvas.yview_scroll(int(-1 * event.delta), "units")
else:
if event.num == 4:
self.canvas.yview_scroll(-1, "units")
elif event.num == 5:
self.canvas.yview_scroll(1, "units")
def onEnter(self, event): # bind wheel events when the cursor enters the control
if platform.system() == 'Linux':
self.canvas.bind_all("<Button-4>", self.onMouseWheel)
self.canvas.bind_all("<Button-5>", self.onMouseWheel)
else:
self.canvas.bind_all("<MouseWheel>", self.onMouseWheel)
def onLeave(self, event): # unbind wheel events when the cursorl leaves the control
if platform.system() == 'Linux':
self.canvas.unbind_all("<Button-4>")
self.canvas.unbind_all("<Button-5>")
else:
self.canvas.unbind_all("<MouseWheel>")
test1 = 100
test2 = 100
test3 = 100
test4 = 100
root = ScrollFrame(tk.Tk())
# first group of labels & buttons
label = tk.Label(root, text="test1")
label.grid(row=0, column=0, columnspan=2)
label = tk.Label(root, text=test1)
label.grid(row=1, column=0, columnspan=2)
button = tk.Button(root, text="Up")
button.grid(row=2, column=0)
button = tk.Button(root, text="Down")
button.grid(row=2, column=1)
#
label = tk.Label(root, text="test2")
label.grid(row=3, column=0, columnspan=2)
label = tk.Label(root, text=test2)
label.grid(row=4, column=0, columnspan=2)
button = tk.Button(root, text="Up")
button.grid(row=5, column=0)
button = tk.Button(root, text="Down")
button.grid(row=5, column=1)
#
label = tk.Label(root, text="test3")
label.grid(row=6, column=0, columnspan=2)
label = tk.Label(root, text=test3)
label.grid(row=7, column=0, columnspan=2)
button = tk.Button(root, text="Up")
button.grid(row=8, column=0)
button = tk.Button(root, text="Down")
button.grid(row=8, column=1)
#
label = tk.Label(root, text="test4")
label.grid(row=9, column=0, columnspan=2)
label = tk.Label(root, text=test4)
label.grid(row=10, column=0, columnspan=2)
button = tk.Button(root, text="Up")
button.grid(row=11, column=0)
button = tk.Button(root, text="Down")
button.grid(row=11, column=1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment