Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tkinter scrollbar for frame

My objective is to add a vertical scroll bar to a frame which has several labels in it. The scroll bar should automatically enabled as soon as the labels inside the frame exceed the height of the frame. After searching through, I found this useful post. Based on that post I understand that in order to achieve what i want, (correct me if I am wrong, I am a beginner) I have to create a Frame first, then create a Canvas inside that frame and stick the scroll bar to that frame as well. After that, create another frame and put it inside the canvas as a window object. So, I finally come up with this:

from Tkinter import *  def data():     for i in range(50):        Label(frame,text=i).grid(row=i,column=0)        Label(frame,text="my text"+str(i)).grid(row=i,column=1)        Label(frame,text="..........").grid(row=i,column=2)  def myfunction(event):     canvas.configure(scrollregion=canvas.bbox("all"),width=200,height=200)  root=Tk() sizex = 800 sizey = 600 posx  = 100 posy  = 100 root.wm_geometry("%dx%d+%d+%d" % (sizex, sizey, posx, posy))  myframe=Frame(root,relief=GROOVE,width=50,height=100,bd=1) myframe.place(x=10,y=10)  canvas=Canvas(myframe) frame=Frame(canvas) myscrollbar=Scrollbar(myframe,orient="vertical",command=canvas.yview) canvas.configure(yscrollcommand=myscrollbar.set)  myscrollbar.pack(side="right",fill="y") canvas.pack(side="left") canvas.create_window((0,0),window=frame,anchor='nw') frame.bind("<Configure>",myfunction) data() root.mainloop() 
  1. Am I doing it right? Is there better/smarter way to achieve the output this code gave me?
  2. Why must I use grid method? (I tried place method, but none of the labels appear on the canvas.)
  3. What so special about using anchor='nw' when creating window on canvas?

Please keep your answer simple, as I am a beginner.

like image 239
Chris Aung Avatar asked Apr 24 '13 09:04

Chris Aung


People also ask

Are frames scrollable tkinter?

A scrollbar is a widget that is useful to scroll the text in another widget. For example, the text in Text, Canvas Frame or Listbox can be scrolled from top to bottom or left to right using scrollbars.

How do I add a scrollbar to Treeview?

The Treeview widget allows the user to add a large number of lists along with the properties that can be customized instantly. If you want to attach a vertical scrollbar to the list of items in a Treeview widget, then you can define a constructor of Scrollbar and configure it by adding the command to it.

What is the difference between canvas and frame in tkinter?

A Frame is designed to be a parent container of other widgets. A Canvas is like a canvas that you can draw somethings on it like lines, circles, text, etc. A Canvas can be used as a parent container as well but it is not designed for that at the first place.


1 Answers

Please note that the proposed code is only valid with Python 2

Here is an example:

from Tkinter import *   # from x import * is bad practice from ttk import *  # http://tkinter.unpythonic.net/wiki/VerticalScrolledFrame  class VerticalScrolledFrame(Frame):     """A pure Tkinter scrollable frame that actually works!     * Use the 'interior' attribute to place widgets inside the scrollable frame     * Construct and pack/place/grid normally     * This frame only allows vertical scrolling      """     def __init__(self, parent, *args, **kw):         Frame.__init__(self, parent, *args, **kw)                      # create a canvas object and a vertical scrollbar for scrolling it         vscrollbar = Scrollbar(self, orient=VERTICAL)         vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)         canvas = Canvas(self, bd=0, highlightthickness=0,                         yscrollcommand=vscrollbar.set)         canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)         vscrollbar.config(command=canvas.yview)          # reset the view         canvas.xview_moveto(0)         canvas.yview_moveto(0)          # create a frame inside the canvas which will be scrolled with it         self.interior = interior = Frame(canvas)         interior_id = canvas.create_window(0, 0, window=interior,                                            anchor=NW)          # track changes to the canvas and frame width and sync them,         # also updating the scrollbar         def _configure_interior(event):             # update the scrollbars to match the size of the inner frame             size = (interior.winfo_reqwidth(), interior.winfo_reqheight())             canvas.config(scrollregion="0 0 %s %s" % size)             if interior.winfo_reqwidth() != canvas.winfo_width():                 # update the canvas's width to fit the inner frame                 canvas.config(width=interior.winfo_reqwidth())         interior.bind('<Configure>', _configure_interior)          def _configure_canvas(event):             if interior.winfo_reqwidth() != canvas.winfo_width():                 # update the inner frame's width to fill the canvas                 canvas.itemconfigure(interior_id, width=canvas.winfo_width())         canvas.bind('<Configure>', _configure_canvas)   if __name__ == "__main__":      class SampleApp(Tk):         def __init__(self, *args, **kwargs):             root = Tk.__init__(self, *args, **kwargs)               self.frame = VerticalScrolledFrame(root)             self.frame.pack()             self.label = Label(text="Shrink the window to activate the scrollbar.")             self.label.pack()             buttons = []             for i in range(10):                 buttons.append(Button(self.frame.interior, text="Button " + str(i)))                 buttons[-1].pack()      app = SampleApp()     app.mainloop() 

It does not yet have the mouse wheel bound to the scrollbar but it is possible. Scrolling with the wheel can get a bit bumpy, though.

edit:

to 1)
IMHO scrolling frames is somewhat tricky in Tkinter and does not seem to be done a lot. It seems there is no elegant way to do it.
One problem with your code is that you have to set the canvas size manually - that's what the example code I posted solves.

to 2)
You are talking about the data function? Place works for me, too. (In general I prefer grid).

to 3)
Well, it positions the window on the canvas.

One thing I noticed is that your example handles mouse wheel scrolling by default while the one I posted does not. Will have to look at that some time.

like image 174
Gonzo Avatar answered Sep 27 '22 19:09

Gonzo