-1

I'm having issues adding a scrollbar to my grid layout using Tkinter and python. I have found similar posts on stackoverflow regarding this topic, but they make use of objects which I do not want to do.

I'm using a canvas to which I add a frame and scrollbar then I add my content to the frame.

When this is displayed the content appears as expected and a scrollbar also exists but the scrollbar does not function.

Can someone help identify the issue in the code below (without using objects)?

from Tkinter import *
top = Tk()
top.geometry("100x100+10+10")
ALL = N+S+E+W
padding = 2
width = 3

frame = Frame(top)
frame.rowconfigure(0, weight=1)
frame.columnconfigure(0, weight=1)
frame.pack(expand=1, fill=BOTH, padx=1, pady=1)

canvas = Canvas(frame)
canvas.grid(row=0, column=0, sticky=NW+SE)

def add_checkbox(x,y):
    check = IntVar()
    Checkbutton(canvas,     variable=check).grid(row=x,column=y,padx=padding,pady=padding)

def add_label(x,y,text):
    Label(canvas, text=text).grid(row=x, column=y, padx=padding, pady=padding)  

add_label(0,0,"x")
add_label(1,0,"y") 
add_label(2,0,"z") 
add_label(3,0,"1") 
add_label(4,0,"2") 
add_label(5,0,"3") 
add_label(5,0,"4") 
add_label(5,0,"5") 
add_label(5,0,"6") 

Button(frame, text="Submit").grid(row=3, column=0, columnspan=width, sticky=ALL)

yscrollbar = Scrollbar(frame, orient=VERTICAL)
yscrollbar.grid(row=0, column=1, sticky=NE+SE)

canvas.configure(yscrollcommand=yscrollbar.set,     scrollregion=canvas.bbox("all"))
canvas.create_window((4,4), window=frame, anchor="nw")
yscrollbar.configure(command=canvas.yview)

frame.pack()
top.mainloop()
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
user1220022
  • 11,167
  • 19
  • 41
  • 57
  • The code you posted has no chance of working -- it has several bugs. For example, you don't define `start` or `y` before using them. Also, `add_checkbox` takes two arguments but you're passing it three. Please post code that actually works. – Bryan Oakley Jul 06 '15 at 14:25
  • Hi Bryan, I have updated the code to a 'working' sample based on some of your previous comments, however the scroll bar still does not work as expected. – user1220022 Jul 06 '15 at 15:25
  • You still aren't using `create_window`, which you _must_ do to enable the scrolling. – Bryan Oakley Jul 06 '15 at 15:41
  • I'm not sure if you saw my most recent edit, I do use it on the 4th last line. – user1220022 Jul 06 '15 at 15:43
  • You're computing the bbox before adding the item to the canvas. Like I mentioned in my answer, you must add items before calling `bbox` -- it can only account for things that are actually on the canvas. You will also probably need to call `update_idletasks()` to force the frame to lay out the children widgets. Otherwise the frame size will be 1x1. – Bryan Oakley Jul 06 '15 at 15:48
  • I moved the call to `bbox` to be the last item before calling the `mainloop`. I also added used `frame.update_idletasks()` and `canvas.update_idletasks()` but it still wont scroll. Do you have any other ideas? – user1220022 Jul 06 '15 at 16:10
  • 1
    I can't critique each change you make to the code. You seem to be just throwing random code in without understanding the actual problem. There are plenty of examples of how to do this on the internet. Start here: http://stackoverflow.com/a/7734187/7432 – Bryan Oakley Jul 06 '15 at 16:27
  • I've marked this as a duplicate, and edited the original with a non-OO example. – Bryan Oakley Jul 06 '15 at 16:44

1 Answers1

1

You have two problems. The first is that you are adding the frame to the canvas incorrectly. The canvas can only scroll canvas objects. That means you cannot pack or grid the frame in the canvas, you must use the create_window method of the canvas.

Also, you have to configure the scrollable region of the canvas, so that the scrollbar knows how much of the canvas is scrollable.

For example, to set the scrollable region to include everything in the canvas you woud do something like this:

canvas.configure(scrollregion=canvas.bbox("all"))

This has to be done after the items have been added, since the bbox method returns the coordinates ("bounding box") of an area then encompasses all canvas objects).

When using this to control a frame, you have to make sure to do this after the frame has had a chance to lay out its children. This is tupically done in a callback to the <Configure> event of the canvas, which happens whenever the canvas is resized or made visible.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • Thanks for your response. I tried modifiying the code using your suggestions, but I still have the same 'error', where the scrollbar does not function. – user1220022 Jul 06 '15 at 13:22
  • @user1220022: I've updated my answer to address the fact that you're adding the frame to the canvas incorrectly, which is definitely part of the problem. – Bryan Oakley Jul 06 '15 at 14:25
  • Thanks for your help. I have made some progress based on your comments, but the scrolling still does not work. I have updated the code to a working example (working to the extend it isn't working as expected). – user1220022 Jul 06 '15 at 15:24