Hello. When I tried to make Tkinter canvas widget respond to MouseWheel event on Windows XP, I failed. The canvas just doesn't receive MouseWheel event. I used bind_all to find out which widget receives this event and the result showed that only the top Tk widget gets it. This is really annoying. I wonder if this problem exists on other platform. I googled, but found no appliable solution, so I wrote one as following. It's not perfect, but works well for me. Please comment on my implementation, and if you have better solution, please show it.
In this implementation, I bind the MouseWheel to the toplevel window which contains the canvas. To test if the canvas shall scroll, I check if the coordinates of the mouse is within the canvas. from Tkinter import * class ScrolledCanvas(Canvas): def __init__(self, parent, xscroll=False, yscroll=False, *args, **kargs): frm = Frame(parent) frm1 = Frame(frm) Canvas.__init__(self, frm1, *args, **kargs) self.pack(side=LEFT, fill=BOTH, expand=YES) frm1.pack(side=TOP, fill=BOTH, expand=YES) frm2 = Frame(frm) frm2.pack(side=BOTTOM, expand=YES, fill=X) if xscroll: xsbar = Scrollbar(frm2) xsbar.config(orient=HORIZONTAL) xsbar.config(command=self.xview) self.config(xscrollcommand=xsbar.set) xsbar.pack(fill=BOTH, expand=YES) self.winfo_toplevel().bind('<Control-MouseWheel>', self.onMouseWheelX) if yscroll: ysbar = Scrollbar(frm1) ysbar.config(orient=VERTICAL) ysbar.config(command=self.yview) self.config(yscrollcommand=ysbar.set) ysbar.pack(side=RIGHT, fill=BOTH, expand=YES) self.winfo_toplevel().bind('<MouseWheel>', self.onMouseWheelY) self.pack = frm.pack # because the canvas is not contained in a frame self.canvasFrame = frm def onMouseWheelY(self, event): if event.widget == self.winfo_toplevel() and \ self.bInCanvas(event.x, event.y): self.yview_scroll(-event.delta, UNITS) def onMouseWheelX(self, event): if event.widget == self.winfo_toplevel() and \ self.bInCanvas(event.x, event.y): self.xview_scroll(-event.delta, UNITS) def bInCanvas(self, x, y): if x > self.canvasFrame.winfo_x() and \ y > self.canvasFrame.winfo_y() and \ x < self.canvasFrame.winfo_x() + int(self.winfo_width()) and \ y < self.canvasFrame.winfo_y() + int(self.winfo_height()): return True return False def test(): top = Frame() top.pack(expand=YES, fill=BOTH) sc = ScrolledCanvas(top, xscroll=True, yscroll=True, bg='Brown', relief=SUNKEN) sc.config(scrollregion=(0,0,1000, 1000)) sc.config(yscrollincrement=1) sc.config(xscrollincrement=1) sc.pack() for i in range(10): sc.create_text(150, 50+(i*100), text='spam'+str(i), fill='beige') top.mainloop() if __name__ == '__main__': test() -- http://mail.python.org/mailman/listinfo/python-list