Tkinter binding a scrollbar to a frame

I’m trying to code an AI for finding the path in a maze. The maze can be made by dragging and dropping a block onto a grid, and for the grid there’s a separate frame. Whenever i try to bind scrollbars to the frame I get this error:

Traceback (most recent call last):
  File "C:\Users\DEVDHRITI\Desktop\Files&Folders\HMMMMM\path finder\path finder.pyw", line 62, in <module>
    grid = Frame(root, yscrollcommand = yscrollbar.set, xscrollcommand = xscrollbar.set)
  File "C:\Users\DEVDHRITI\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 3153, in __init__
    Widget.__init__(self, master, 'frame', cnf, {}, extra)
  File "C:\Users\DEVDHRITI\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 2601, in __init__
    self.tk.call(
_tkinter.TclError: unknown option "-yscrollcommand"

Here’s my code:

from tkinter import *
from threading import Thread



class Setting:

	
	def __init__(self):

		settings = {}

		file = open("user-setting.setting", "r")
		self.file = file

		for pair in file.read().split("\n"):

			exec("settings.update({" + pair + "})")

		self.settings = settings

	
	def edit(self, setting, new_setting):

		self.settings[setting] = new_setting


	def reopen(self):

		self.file = open("user-setting.setting", "r")

	
	def save(self):

		self.file.close()
		file = open("user-setting.setting","w")

		for x in self.settings:

			file.write('"' + x + '"' + ":" + self.settings[x])



settings = Setting()

root = Tk()
root.geometry(settings.settings["geometry"])


def save():

	settings.settings["geometry"] = root.geometry()
	settings.save()


root.protocol("WM_DELETE_WINDOW", save)

yscrollbar = Scrollbar(root, orient = "vertical")
xscrollbar = Scrollbar(root, orient = "horizontal")

ribbon = Frame(root, height = 40, borderwidth = 5)
grid = Frame(root, yscrollcommand = yscrollbar.set, xscrollcommand = xscrollbar.set)

yscrollbar.pack(fill = "y", side = "right")
xscrollbar.pack(fill = "x", side = "bottom")

ribbon.pack(fill = "x", side = "top")
grid.pack(fill = "both", expand = True)

yscrollbar.config(command = grid.yview)
xscrollbar.config(command = grid.xview)



root.mainloop()

Anyone know why is this happening? I’m using python 3.10,0, if it helps

When you look at the tk frame documentation you see there are no xscrollcommand or yscrollcommand options. So frame is not scrollable, you can’t add scrollbars to a frame.

For scrollable text use the text class, for graphics use a canvas. Some other widgets, like the listbox, also support scrollbars.

@Mholscher so isn’t there any widget container which is scrollable?

Well, if you don’t count the fact that things like Listbox and Canvas and ttk.Treeview and Entry are really also containers, no, there are none. I have not needed a “general purpose container”, so I did not look. But now I did and have not found one.

A general purpose container having scrolling would not sit well with tk. A container in tk is sized and afterwards the contained widgets are sized to fit the container. When would the scrollbar have effect, i.e. when would it start scrolling? When you resize the window, it resizes the widgets according to the rules you have set.

k thx for the help @Mholscher

To make an arbitrary widget scrollable, you have to use a canvas, and then the create_window() method to insert that other widget into the canvas. Something like this:

canvas = tk.Canvas(window)
child_frame = tk.Frame(canvas)
canvas.create_window(0, 0, window=child_frame, anchor="nw")
def update_size(e=None):
    canvas["scrollregion"] = canvas.bbox("all")
canvas.bind('<Configure>', update_size)
canvas.after_idle(update_size)

The bind command is a weird thing, you need to update whenever the window changes size to tell it what part can be scrolled. bbox("all") returns the size of the contents, which is what you probably need.
Since you’re dragging stuff onto the the window, you might be able to avoid the frame actually and just place images/other graphics directly.