tkinter: binding mousewheel to scrollbar tkinter: binding mousewheel to scrollbar tkinter tkinter

tkinter: binding mousewheel to scrollbar


Perhaps the simplest solution is to make a global binding for the mousewheel. It will then fire no matter what widget is under the mouse or which widget has the keyboard focus. You can then unconditionally scroll the canvas, or you can be smart and figure out which of your windows should scroll.

For example, on windows you would do something like this:

self.canvas = Canvas(...)self.canvas.bind_all("<MouseWheel>", self._on_mousewheel)...def _on_mousewheel(self, event):    self.canvas.yview_scroll(-1*(event.delta/120), "units")

Note that self.canvas.bind_all is a bit misleading -- you more correctly should call root.bind_all but I don't know what or how you define your root window. Regardless, the two calls are synonymous.

Platform differences:

  • On Windows, you bind to <MouseWheel> and you need to divide event.delta by 120 (or some other factor depending on how fast you want the scroll)
  • on OSX, you bind to <MouseWheel> and you need to use event.delta without modification
  • on X11 systems you need to bind to <Button-4> and <Button-5>, and you need to divide event.delta by 120 (or some other factor depending on how fast you want to scroll)

There are more refined solutions involving virtual events and determining which window has the focus or is under the mouse, or passing the canvas window reference through the binding, but hopefully this will get you started.


Based on @BryanOakley's answer, here is a way to scroll only the focused widget (i.e. the one you have mouse cursor currently over).

Bind to <Enter> and <Leave> events happening on your scrollable frame which sits inside a canvas, the following way (scrollframe is the frame that is inside the canvas):

    ...    self.scrollframe.bind('<Enter>', self._bound_to_mousewheel)    self.scrollframe.bind('<Leave>', self._unbound_to_mousewheel)    return Nonedef _bound_to_mousewheel(self, event):    self.canv.bind_all("<MouseWheel>", self._on_mousewheel)def _unbound_to_mousewheel(self, event):    self.canv.unbind_all("<MouseWheel>")def _on_mousewheel(self, event):    self.canv.yview_scroll(int(-1*(event.delta/120)), "units")


This link gives you an example as to how to use the scrollwheel.

http://www.daniweb.com/software-development/python/code/217059/using-the-mouse-wheel-with-tkinter-python

I hope this helps!

# explore the mouse wheel with the Tkinter GUI toolkit# Windows and Linux generate different events# tested with Python25import Tkinter as tkdef mouse_wheel(event):    global count    # respond to Linux or Windows wheel event    if event.num == 5 or event.delta == -120:        count -= 1    if event.num == 4 or event.delta == 120:        count += 1    label['text'] = countcount = 0root = tk.Tk()root.title('turn mouse wheel')root['bg'] = 'darkgreen'# with Windows OSroot.bind("<MouseWheel>", mouse_wheel)# with Linux OSroot.bind("<Button-4>", mouse_wheel)root.bind("<Button-5>", mouse_wheel)label = tk.Label(root, font=('courier', 18, 'bold'), width=10)label.pack(padx=40, pady=40)root.mainloop()