If you don't mind a little trickery, you can simulate what you want. It's a bit of a hack though.
The trick is that when you call tk.Frame.__init__
, you need to be giving it the canvas as the parent, making self
the content frame. Of course, to do that you have to create the canvas first, and to create the canvas you have to create the outer frame.
It looks something like this:
class scrolledFrame(tk.Frame):
def __init__(self, parent):
self.outer = tk.Frame(parent)
self.canvas = tk.Canvas(self.outer)
self.scroll = tk.Scrollbar(self.outer, command = self.canvas.yview)
tk.Frame.__init__(self, self.canvas)
self.contentWindow = self.canvas.create_window((0,0), window = self, anchor = "nw")
However, when you do the above and you try to call pack
, place
, or grid
on the instance of scrolledFrame
it's going to do the wrong thing since the instance points to the inner frame rather than the outer frame.
Here's the trickery: the solution to that is to redirect calls to pack
, place
, and grid
to the outer frame.
class scrolledFrame(tk.Frame):
def __init__(self, parent):
...
self.pack = self.outer.pack
self.place = self.outer.place
self.grid = self.outer.grid
With that, you can use scrolledFrame
like you want, as long as you use pack
, place
, or grid
when adding it to the layout.
exampleFrame = scrolledFrame(root)
exampleFrame.pack(fill="both", expand=True)
for i in range(100):
exampleLabel = tk.Label(exampleFrame, text = f"I'm in the scrolled frame! ({i})")
exampleLabel.pack()
Here's a complete working example, though I've removed the mousewheel code for brevity.
import tkinter as tk
class scrolledFrame(tk.Frame):
def __init__(self, parent):
self.outer = tk.Frame(parent)
self.canvas = tk.Canvas(self.outer)
self.scroll = tk.Scrollbar(self.outer, command = self.canvas.yview)
tk.Frame.__init__(self, self.canvas)
self.contentWindow = self.canvas.create_window((0,0), window = self, anchor = "nw")
self.canvas.pack(fill = "both", expand = True, side = "left")
self.scroll.pack(side = "right", fill = "y")
self.canvas.config(yscrollcommand = self.scroll.set)
self.bind("<Configure>", self.resizeCanvas)
self.pack = self.outer.pack
self.place = self.outer.place
self.grid = self.outer.grid
def resizeCanvas(self, event):
self.canvas.config(scrollregion = self.canvas.bbox("all"))
self.canvas.itemconfig(self.contentWindow, width = self.canvas.winfo_width())
root = tk.Tk()
exampleFrame = scrolledFrame(root)
exampleFrame.pack(fill="both", expand=True)
for i in range(100):
exampleLabel = tk.Label(exampleFrame, text = f"I'm in the scrolled frame! ({i})")
exampleLabel.pack(fill="x")
root.mainloop()