Custom Tkinter scrollbar

Hunter.lennon at gmail.com Hunter.lennon at gmail.com
Sat Nov 24 11:27:12 CET 2007


I ended up giving up on doing the scrollbar as a separate class, which
is probably for the best.  This is the pertinent code for what I
wanted, and it does what I need it to do.  I found the canvas-moving-w-
mouse.py program helpful in getting started with this; some of the
code is directly from that example.  I'm posting my code on the off
chance someone will find something of use in it.

            #Constants for the scrollbar icon range.
            self.UPPER_LIMIT = 160
            self.LOWER_LIMIT = 334

#Prepare pictures
            self.upArrow = tk.PhotoImage ("upArrow", file =
"upArrow.gif")
            self.scrollIcon = tk.PhotoImage ("scrollIcon", file =
"scrollIcon.gif")
            self.downArrow = tk.PhotoImage ("downArrow", file =
"downArrow.gif")



#Main Canvas
            self.shell = tk.Canvas (parent, width = 388, height = 408,
                                    borderwidth = - 2)
            self.shell.create_image (0, 0, image = self.shell_image,
                                      anchor = tk.NW)
            self.shell.create_image (361, 9, image = self.exit_image,
                                      anchor = tk.NW, tags = "Exit")

#Inner frame that contains a canvas.
#This is what is scrolled by the scrollbar.
            self.masteryFrame = tk.Frame (parent, borderwidth = -2)
            self.masteryCanvas = tk.Canvas (self.masteryFrame, width =
326, height = 218,
                                            scrollregion =
(0,0,326,439), borderwidth = -2)
            self.masteryCanvas.pack()
            self.masteryFrame.pack()
            self.masteryCanvas.create_image (0, 0, image =
"masteryFrame", anchor = tk.NW)
            self.shell.create_window (22, 135, window =
self.masteryFrame,
                                      width = 326, height = 218,
anchor = tk.NW)


            #Scrollbar
            self.shell.create_image (350, 136, image = self.upArrow,
anchor = tk.NW,
                                     tags = "upArrow")
            self.shell.create_image (357, 160, image =
self.scrollIcon, tags = "scroll")
            self.shell.create_image (350, 343, image = self.downArrow,
anchor = tk.NW,
                                     tags = "downArrow")

            self.shell.tag_bind ("scroll", "<Button-1>",
self.mouseDown)
            self.shell.tag_bind ("scroll", "<B1-Motion>",
self.mouseMove)
            self.shell.tag_bind ("upArrow", "<ButtonRelease-1>",
self.stepUp)
            self.shell.tag_bind ("downArrow", "<ButtonRelease-1>",
self.stepDown)
            self.shell.tag_bind ("Exit", "<Button-1>", self.close)

            self.shell.pack (side = tk.LEFT)



        def mouseDown (self, event):
            #Scrollbar Function
            #Remember where the mouse went down"
            self.lastx = event.x
            self.lasty = event.y

        def mouseMove (self, event):
            #Scrollbar Function
            #Whatever the mouse is over is automatically tagged as
current by tk.
            #Only moves vertically.
            #Keep the cursor in bounds:
            if event.y >= self.UPPER_LIMIT and event.y <=
self.LOWER_LIMIT:
                self.shell.move(tk.CURRENT, 0, event.y - self.lasty)
                self.lasty = event.y
            elif event.y < self.UPPER_LIMIT:
                self.shell.coords(tk.CURRENT, 357, self.UPPER_LIMIT )
                self.lasty = event.y
            elif event.y > 334:
                self.shell.coords(tk.CURRENT, 357, self.LOWER_LIMIT)
                self.lasty = event.y
            self.masteryCanvas.yview_moveto (self.scrollbarPosition())


        def stepUp (self, event):
            #Scrollbar Function
            #Move up one row or to the top, whichever is less.
            #43.5 causes the canvas to move one row.
            next = self.shell.coords ("scroll")[1] - 43.5
            if next >= self.UPPER_LIMIT:
                self.shell.coords ("scroll", 357, next)
            else:
                self.shell.coords ("scroll", 357, self.UPPER_LIMIT)
            self.masteryCanvas.yview_moveto (self.scrollbarPosition())

        def stepDown (self, event):
            #Scrollbar Function
            #Move down one row or to the bottom, whichever is less.
            #43.5 causes the canvas to move one row.
            next = self.shell.coords ("scroll")[1] + 43.5
            if next <= self.LOWER_LIMIT:
                self.shell.coords( "scroll", 357, next)
            else:
                self.shell.coords( "scroll", 357, self.LOWER_LIMIT)
            self.masteryCanvas.yview_moveto (self.scrollbarPosition())


        def scrollbarPosition (self):
            #Scrollbar Function that computes movement
            #Return a value between 0 and .5 for moving the canvas.
            yCoord = self.shell.coords ("scroll")[1]
            length = self.LOWER_LIMIT - self.UPPER_LIMIT
            current = yCoord - self.UPPER_LIMIT
            current /= 2
            #print current / length
            return (current / length)



More information about the Python-list mailing list