The scrollbars in Tkinter kind of suck.. Imagine a todo app that lists the todo items along with corresponding checkboxes in a vertical list. When the list gets long, it might extend beyond the bottom of the window. A scrollbar can solve that no problem, BUT, with Tkinter the scrollbars do not automatically include the new todo items in the scrollable area. So all those super important action items are now out of reach! Unfortunately, it’s not straight forward to fix this issue with Tkinter and there are no examples online of how to get both vertical and horizontal scrolling working for a dynamic app. It took me a few hours, but I developed a robust solution that will get your Tkinter todo list app, chess app, or whatever-else-your-heart-desires app scrolling properly in no time.

First create the window, containers for content, and scrollbars. The only native scrollable container in Tkinter is a canvas, so add that to the window with a frame inside. The frame is where widgets will go since widgets can’t be added directly to a canvas.

root = tk.Tk()

cTableContainer = tk.Canvas(root)
fTable = tk.Frame(cTableContainer)
sbHorizontalScrollBar = tk.Scrollbar(root)
sbVerticalScrollBar = tk.Scrollbar(root)


Now that we have the window setup, let’s configure the scrollbars. Attach the horizontal and vertical scrollbars to the canvas and position them at the bottom and right side of the screen where they belong. Then bind the scroll events the the proper container.

cTableContainer.config(xscrollcommand=sbHorizontalScrollBar.set,
yscrollcommand=sbVerticalScrollBar.set, highlightthickness=0)
sbHorizontalScrollBar.config(orient=tk.HORIZONTAL, command=cTableContainer.xview)
sbVerticalScrollBar.config(orient=tk.VERTICAL, command=cTableContainer.yview)

sbHorizontalScrollBar.pack(fill=tk.X, side=tk.BOTTOM, expand=tk.FALSE)
sbVerticalScrollBar.pack(fill=tk.Y, side=tk.RIGHT, expand=tk.FALSE)
cTableContainer.pack(fill=tk.BOTH, side=tk.LEFT, expand=tk.TRUE)
cTableContainer.create_window(0, 0, window=fTable, anchor=tk.NW)


Finally, here is the magic function that updates the scrollable area. Just call it when you add a new widget to the frame. This took me well over any hour of reading the docs and forums to come up with. I’ll spare you the misery.

def updateScrollRegion():