0

So I have been trying to make a scrollable frame. I've had been searching and these 3 had the most impact:
https://stackoverflow.com/questions/16188420/tkinter-scrollbar-for-frame\ https://stackoverflow.com/questions/3085696/adding-a-scrollbar-to-a-group-of-widgets-in-tkinter\ How could I get a Frame with a scrollbar in Tkinter?

And I have come up with the following code:

from tkinter import *

class Test_tk_stuff():
    def __init__(self):
        self.screen = Tk()
        self.screen.geometry("500x500")

        self.structure()

        self.screen.mainloop()

    def scroller(self, canvas):
        canvas.configure(scrollregion = canvas.bbox("all"))

    def frame_expander(self, event):
        canvas_width = event.width
        self.canvas.itemconfig(self.frame, width = canvas_width)

    def structure(self):
        parent = Frame(self.screen)
        parent.pack(expand = True, fill = BOTH)
        
        self.canvas = Canvas(parent, bg = "green", highlightthickness = 0, relief = RAISED)
        self.frame = Frame(self.canvas, bg = "blue")

        myscrollbar = Scrollbar(parent, orient = "vertical", command = self.canvas.yview)
        self.canvas.configure(yscrollcommand = myscrollbar.set)

        myscrollbar.pack(side = RIGHT, fill = Y)

        self.canvas.pack(side = LEFT, fill = BOTH, expand = True)

        self.canvas.create_window((0, 0), window = self.frame)
        # can't do: self.frame.pack(expand = True, fill = BOTH) because it will become unscrollable

        # Event Bind        
        self.frame.bind("<Configure>", lambda event, canvas = self.canvas: self.scroller(self.canvas))
        self.canvas.bind("<Configure>", self.frame_expander)

        # initialize number of minimum columns
        for num_columns in range(3):
            self.frame.columnconfigure(num_columns, weight = 1)

        a = "Button Text!"

        # fill it to - 1.) test scrollbar 2.) actually using the frame inside
        for place2 in range(10):
            Button(self.frame, text = a, bg = "black", fg = "white").grid(row = place2, column = 1, sticky = "NSEW", ipady = 15)

if __name__ == "__main__":
    Test_tk_stuff()

But somehow when I run it, it shows a _tkinter.TclError. I tried searching what that is and how to fix it, but, as you can see, I wasn't able to fix it.

Is there something wrong with my implementation? Thanks in advance.

  • Note that `canvas.itemconfig()` is used on canvas items returned by `canvas.create_xxxx()` functions, not on tkinter widget (`self.frame`). Use `self.frame.config(width=canvas_width)` instead. – acw1668 Apr 08 '21 at 10:09

2 Answers2

1

use self.frame.config(width=canvas_width) instead of canvas.itemconfig()

vandit vasa
  • 413
  • 4
  • 20
1

canvas.itemconfig() is used on canvas item returned by canvas.create_xxxxx() functions, not on tkinter widget (self.frame).

Save the canvas item ID for the self.frame and use it in canvas.itemconfig():


def frame_expander(self, event):
    canvas_width = event.width
    self.canvas.itemconfig(self.frame_item, width=canvas_width)

def structure(self):
    ...
    self.frame_item = self.canvas.create_window((0, 0), window = self.frame)
    ...
acw1668
  • 40,144
  • 5
  • 22
  • 34