469,591 Members | 1,601 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,591 developers. It's quick & easy.

Make Tkinter canvas respond to MouseWheel event

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()

Mar 1 '07 #1
0 2164

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by syed_saqib_ali | last post: by
3 posts views Thread by Gigs_ | last post: by
4 posts views Thread by Davy | last post: by
4 posts views Thread by skanemupp | last post: by
4 posts views Thread by skanemupp | last post: by
3 posts views Thread by skanemupp | last post: by
3 posts views Thread by joshdw4 | last post: by
1 post views Thread by Eric_Dexter | last post: by
reply views Thread by suresh191 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.