I have this scroll-able frame (frame inside canvas actually).
import Tkinter as tk
class Scrollbarframe():
def __init__(self, parent,xsize,ysize,xcod,ycod):
def ScrollAll(event):
canvas1.configure(scrollregion=canvas1.bbox("all"),width=xsize,height=ysize,bg='white')
self.parent=parent
self.frame1=tk.Frame(parent,bg='white')
self.frame1.place(x=xcod,y=ycod)
canvas1=tk.Canvas(self.frame1)
self.frame2=tk.Frame(canvas1,bg='white',relief='groove',bd=1,width=1230,height=430)
scrollbar1=tk.Scrollbar(self.frame1,orient="vertical",command=canvas1.yview)
canvas1.configure(yscrollcommand=scrollbar1.set)
scrollbar1.pack(side="right",fill="y")
canvas1.pack(side="left")
canvas1.create_window((0,0),window=self.frame2,anchor='nw')
self.frame2.bind("<Configure>",ScrollAll)
I would like to bind mouse wheel to the scrollbar so that user can scroll down the frame without having to use arrow buttons on the scrollbar. After looking around, i added a binding to my canvas1
like this
self.frame1.bind("<MouseWheel>", self.OnMouseWheel)
This is the function:
def OnMouseWheel(self,event):
self.scrollbar1.yview("scroll",event.delta,"units")
return "break"
But the scroll bar won't move when i use mousewheel. Can anyone help me with this? All i want is when the user use mousewheel (inside the frame area/on the scrollbar), the canvas should automatically scroll up or down.
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):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:
Note that
self.canvas.bind_all
is a bit misleading -- you more correctly should callroot.bind_all
but I don't know what or how you define your root window. Regardless, the two calls are synonymous.Platform differences:
<MouseWheel>
and you need to divideevent.delta
by 120 (or some other factor depending on how fast you want the scroll)<MouseWheel>
and you need to useevent.delta
without modification<Button-4>
and<Button-5>
, and you need to divideevent.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.
In case you are interested
How to scroll 2 listbox at the same time
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!
To get rid of the weird factor 120 we could just look at the sign of the event.delta value. This makes it easy to use the same handler under Windows, Linux and Mac OS.