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) -- http://mail.python.org/mailman/listinfo/python-list