# Author: Miguel Martinez Lopez
# Uncomment the next line to see my email
# print "Author's email: ", "61706c69636163696f6e616d656469646140676d61696c2e636f6d".decode("hex")
try:
import Tkinter as tk
import ttk
except ImportError:
import tkinter as tk
from tkinter import ttk
class MouseWheel(object):
def __init__(self, root, factor = 0.5):
self.activeArea = None
self.factor = factor
import platform
os = platform.system()
if os == "Linux" :
root.bind_all('<4>', self.onMouseWheel, add='+')
root.bind_all('<5>', self.onMouseWheel, add='+')
else:
# Windows and MacOS
root.bind_all("<MouseWheel>", self.onMouseWheel, add='+')
def onMouseWheel(self,event):
if self.activeArea:
self.activeArea.onMouseWheel(event.delta)
def mouseWheel_bind(self, widget):
self.activeArea = widget
def mouseWheel_unbind(self):
self.activeArea = None
def add_scrolling(self, scrollingArea, xscrollbar=None, yscrollbar=None):
scrollingArea.bind('<Enter>',lambda event: self.mouseWheel_bind(scrollingArea))
scrollingArea.bind('<Leave>', lambda event: self.mouseWheel_unbind())
if xscrollbar and not hasattr(xscrollbar, 'onMouseWheel'):
setattr(xscrollbar, 'onMouseWheel', lambda delta: scrollingArea.xview("scroll",(-1)*int(delta/(120*self.factor)),"units" ) )
if yscrollbar and not hasattr(yscrollbar, 'onMouseWheel'):
setattr(yscrollbar, 'onMouseWheel', lambda delta: scrollingArea.yview("scroll",(-1)*int(delta/(120*self.factor)),"units" ) )
active_scrollbar_on_mouse_wheel = yscrollbar or xscrollbar
if active_scrollbar_on_mouse_wheel:
setattr(scrollingArea, 'onMouseWheel', active_scrollbar_on_mouse_wheel.onMouseWheel)
for scrollbar in (xscrollbar, yscrollbar):
if scrollbar:
scrollbar.bind('<Enter>', lambda event, scrollbar=scrollbar: self.mouseWheel_bind(scrollbar) )
scrollbar.bind('<Leave>', lambda event: self.mouseWheel_unbind())
class simultaneousScrollbar(ttk.Scrollbar):
def __init__(self, master, factor = 0.5, **kwargs):
self.__scrollableWidgets = []
if 'orient' in kwargs:
if kwargs['orient']== tk.VERTICAL:
self.__orientLabel = 'y'
elif kwargs['orient']== tk.HORIZONTAL:
self.__orientLabel = 'x'
else:
raise Exception("Bad 'orient' argument in scrollbar.")
else:
self.__orientLabel = 'y'
kwargs['command'] = self.onScroll
self.factor = factor
ttk.Scrollbar.__init__(self, master, **kwargs)
def add_ScrollableArea(self, *scrollableWidgets):
for widget in scrollableWidgets:
self.__scrollableWidgets.append(widget)
widget[self.__orientLabel+'scrollcommand']=self.set
def onScroll(self, *args):
for widget in self.__scrollableWidgets:
getattr(widget, self.__orientLabel+'view')(*args)
def onMouseWheel(self, delta):
for widget in self.__scrollableWidgets:
getattr(widget, self.__orientLabel+'view')("scroll",(-1)*int(delta/(120*self.factor)),"units" )
def test():
root = tk.Tk()
scrollbar = simultaneousScrollbar(root, orient=tk.HORIZONTAL)
scrollbar.pack(side=tk.TOP, fill=tk.X)
emptySpace = tk.Frame(root, height=18)
emptySpace.pack()
tk.Label(root, text='First scrolled frame:').pack(anchor=tk.W)
canvas1 = tk.Canvas(root, width=300, height=100)
canvas1.pack(anchor=tk.NW)
frame1= tk.Frame(canvas1)
frame1.pack()
for i in range(20):
tk.Label(frame1, text="Label "+str(i)).pack(side=tk.LEFT)
canvas1.create_window(0, 0, window=frame1, anchor='nw')
canvas1.update_idletasks()
canvas1['scrollregion'] = (0,0,frame1.winfo_reqwidth(), frame1.winfo_reqheight())
tk.Label(root, text='Second scrolled frame:').pack(anchor=tk.W)
canvas2 = tk.Canvas(root,width=300, height=100)
canvas2.pack(anchor=tk.NW)
frame2= tk.Frame(canvas2)
frame2.pack()
for i in range(20):
tk.Label(frame2, text="Label "+str(i)).pack(side=tk.LEFT)
canvas2.create_window(0, 0, window=frame2, anchor='nw')
canvas2.update_idletasks()
canvas2['scrollregion'] = (0,0,frame2.winfo_reqwidth(), frame2.winfo_reqheight())
scrollbar.add_ScrollableArea(canvas1,canvas2)
MouseWheel(root).add_scrolling(canvas1, xscrollbar=scrollbar)
MouseWheel(root).add_scrolling(canvas2, xscrollbar=scrollbar)
root.mainloop()
if __name__== '__main__':
test()
Diff to Previous Revision
--- revision 6 2014-06-22 17:03:02
+++ revision 7 2016-11-20 00:29:52
@@ -1,167 +1,140 @@
-# Version: 0.4
# Author: Miguel Martinez Lopez
# Uncomment the next line to see my email
# print "Author's email: ", "61706c69636163696f6e616d656469646140676d61696c2e636f6d".decode("hex")
-
-import Tkinter as tk
-import ttk
-
-import platform
-os = platform.system()
+try:
+ import Tkinter as tk
+ import ttk
+except ImportError:
+ import tkinter as tk
+ from tkinter import ttk
class MouseWheel(object):
- def __init__(self, root, factor = 2):
- global os
-
- self.activeArea = None
-
- if type(factor) == int:
- self.factor = factor
- else:
- raise Exception("Factor must be an integer.")
+ def __init__(self, root, factor = 0.5):
+ self.activeArea = None
+ self.factor = factor
- if os == "Linux" :
- root.bind_all('<4>', self.onMouseWheel, add='+')
- root.bind_all('<5>', self.onMouseWheel, add='+')
- else:
- # Windows and MacOS
- root.bind_all("<MouseWheel>", self.onMouseWheel, add='+')
+ import platform
+ os = platform.system()
- def onMouseWheel(self,event):
- if self.activeArea:
- self.activeArea.onMouseWheel(event)
+ if os == "Linux" :
+ root.bind_all('<4>', self.onMouseWheel, add='+')
+ root.bind_all('<5>', self.onMouseWheel, add='+')
+ else:
+ # Windows and MacOS
+ root.bind_all("<MouseWheel>", self.onMouseWheel, add='+')
- def mouseWheel_bind(self, widget):
- self.activeArea = widget
+ def onMouseWheel(self,event):
+ if self.activeArea:
+ self.activeArea.onMouseWheel(event.delta)
- def mouseWheel_unbind(self):
- self.activeArea = None
+ def mouseWheel_bind(self, widget):
+ self.activeArea = widget
- @staticmethod
- def build_function_onMouseWheel(widget, orient, factor = 1):
- view_command = getattr(widget, orient+'view')
- if os == 'Linux':
- def onMouseWheel(event):
- if event.num == 4:
- view_command("scroll",(-1)*factor,"units" )
- elif event.num == 5:
- view_command("scroll",factor,"units" )
-
- elif os == 'Windows':
- def onMouseWheel(event):
- view_command("scroll",(-1)*int((event.delta/120)*factor),"units" )
-
- elif os == 'Darwin':
- def onMouseWheel(event):
- view_command("scroll",event.delta,"units" )
-
- return onMouseWheel
-
+ def mouseWheel_unbind(self):
+ self.activeArea = None
- def add_scrolling(self, scrollingArea, xscrollbar=None, yscrollbar=None):
- scrollingArea.bind('<Enter>',lambda event: self.mouseWheel_bind(scrollingArea))
- scrollingArea.bind('<Leave>', lambda event: self.mouseWheel_unbind())
+ def add_scrolling(self, scrollingArea, xscrollbar=None, yscrollbar=None):
+ scrollingArea.bind('<Enter>',lambda event: self.mouseWheel_bind(scrollingArea))
+ scrollingArea.bind('<Leave>', lambda event: self.mouseWheel_unbind())
- if xscrollbar and not hasattr(xscrollbar, 'onMouseWheel'):
- setattr(xscrollbar, 'onMouseWheel', self.build_function_onMouseWheel(scrollingArea,'x', self.factor) )
+ if xscrollbar and not hasattr(xscrollbar, 'onMouseWheel'):
+ setattr(xscrollbar, 'onMouseWheel', lambda delta: scrollingArea.xview("scroll",(-1)*int(delta/(120*self.factor)),"units" ) )
- if yscrollbar and not hasattr(yscrollbar, 'onMouseWheel'):
- setattr(yscrollbar, 'onMouseWheel', self.build_function_onMouseWheel(scrollingArea,'y', self.factor) )
+ if yscrollbar and not hasattr(yscrollbar, 'onMouseWheel'):
+ setattr(yscrollbar, 'onMouseWheel', lambda delta: scrollingArea.yview("scroll",(-1)*int(delta/(120*self.factor)),"units" ) )
- active_scrollbar_on_mouse_wheel = yscrollbar or xscrollbar
- if active_scrollbar_on_mouse_wheel:
- setattr(scrollingArea, 'onMouseWheel', active_scrollbar_on_mouse_wheel.onMouseWheel)
+ active_scrollbar_on_mouse_wheel = yscrollbar or xscrollbar
+ if active_scrollbar_on_mouse_wheel:
+ setattr(scrollingArea, 'onMouseWheel', active_scrollbar_on_mouse_wheel.onMouseWheel)
- for scrollbar in (xscrollbar, yscrollbar):
- if scrollbar:
- scrollbar.bind('<Enter>', lambda event, scrollbar=scrollbar: self.mouseWheel_bind(scrollbar) )
- scrollbar.bind('<Leave>', lambda event: self.mouseWheel_unbind())
+ for scrollbar in (xscrollbar, yscrollbar):
+ if scrollbar:
+ scrollbar.bind('<Enter>', lambda event, scrollbar=scrollbar: self.mouseWheel_bind(scrollbar) )
+ scrollbar.bind('<Leave>', lambda event: self.mouseWheel_unbind())
class simultaneousScrollbar(ttk.Scrollbar):
- def __init__(self, master, factor = 2, **kwargs):
- self.__scrollableWidgets = []
- self.__onMouseWheel_callbacks = []
-
- if 'orient' in kwargs:
- if kwargs['orient']== tk.VERTICAL:
- self.__orientLabel = 'y'
- elif kwargs['orient']== tk.HORIZONTAL:
- self.__orientLabel = 'x'
- else:
- raise Exception("Bad 'orient' argument in scrollbar.")
- else:
- self.__orientLabel = 'y'
+ def __init__(self, master, factor = 0.5, **kwargs):
+ self.__scrollableWidgets = []
- kwargs['command'] = self.onScroll
- self.factor = factor
+ if 'orient' in kwargs:
+ if kwargs['orient']== tk.VERTICAL:
+ self.__orientLabel = 'y'
+ elif kwargs['orient']== tk.HORIZONTAL:
+ self.__orientLabel = 'x'
+ else:
+ raise Exception("Bad 'orient' argument in scrollbar.")
+ else:
+ self.__orientLabel = 'y'
- ttk.Scrollbar.__init__(self, master, **kwargs)
+ kwargs['command'] = self.onScroll
+ self.factor = factor
+
+ ttk.Scrollbar.__init__(self, master, **kwargs)
- def add_ScrollableArea(self, *scrollableWidgets):
- for widget in scrollableWidgets:
- self.__scrollableWidgets.append(widget)
- widget[self.__orientLabel+'scrollcommand']=self.set
- onMouseWheel_callback = MouseWheel.build_function_onMouseWheel(widget,self.__orientLabel, self.factor )
- self.__onMouseWheel_callbacks.append(onMouseWheel_callback)
-
- def onScroll(self, *args):
- for widget in self.__scrollableWidgets:
- getattr(widget, self.__orientLabeself.__orientLabell+'view')(*args)
- def onMouseWheel(self, event):
- for callback in self.__onMouseWheel_callbacks:
- callback(event)
-
+ def add_ScrollableArea(self, *scrollableWidgets):
+ for widget in scrollableWidgets:
+ self.__scrollableWidgets.append(widget)
+ widget[self.__orientLabel+'scrollcommand']=self.set
+
+ def onScroll(self, *args):
+ for widget in self.__scrollableWidgets:
+ getattr(widget, self.__orientLabel+'view')(*args)
+
+ def onMouseWheel(self, delta):
+ for widget in self.__scrollableWidgets:
+ getattr(widget, self.__orientLabel+'view')("scroll",(-1)*int(delta/(120*self.factor)),"units" )
+
def test():
- root = tk.Tk()
+ root = tk.Tk()
- scrollbar = simultaneousScrollbar(root, orient=tk.HORIZONTAL)
- scrollbar.pack(side=tk.TOP, fill=tk.X)
+ scrollbar = simultaneousScrollbar(root, orient=tk.HORIZONTAL)
+ scrollbar.pack(side=tk.TOP, fill=tk.X)
- emptySpace = tk.Frame(root, height=18)
- emptySpace.pack()
+ emptySpace = tk.Frame(root, height=18)
+ emptySpace.pack()
- tk.Label(root, text='First scrolled frame:').pack(anchor=tk.W)
- canvas1 = tk.Canvas(root, width=300, height=100)
- canvas1.pack(anchor=tk.NW)
+ tk.Label(root, text='First scrolled frame:').pack(anchor=tk.W)
+ canvas1 = tk.Canvas(root, width=300, height=100)
+ canvas1.pack(anchor=tk.NW)
- frame1= tk.Frame(canvas1)
- frame1.pack()
+ frame1= tk.Frame(canvas1)
+ frame1.pack()
- for i in range(20):
- tk.Label(frame1, text="Label "+str(i)).pack(side=tk.LEFT)
+ for i in range(20):
+ tk.Label(frame1, text="Label "+str(i)).pack(side=tk.LEFT)
- canvas1.create_window(0, 0, window=frame1, anchor='nw')
+ canvas1.create_window(0, 0, window=frame1, anchor='nw')
- canvas1.update_idletasks()
+ canvas1.update_idletasks()
- canvas1['scrollregion'] = (0,0,frame1.winfo_reqwidth(), frame1.winfo_reqheight())
+ canvas1['scrollregion'] = (0,0,frame1.winfo_reqwidth(), frame1.winfo_reqheight())
- tk.Label(root, text='Second scrolled frame:').pack(anchor=tk.W)
- canvas2 = tk.Canvas(root,width=300, height=100)
- canvas2.pack(anchor=tk.NW)
+ tk.Label(root, text='Second scrolled frame:').pack(anchor=tk.W)
+ canvas2 = tk.Canvas(root,width=300, height=100)
+ canvas2.pack(anchor=tk.NW)
- frame2= tk.Frame(canvas2)
- frame2.pack()
+ frame2= tk.Frame(canvas2)
+ frame2.pack()
- for i in range(20):
- tk.Label(frame2, text="Label "+str(i)).pack(side=tk.LEFT)
+ for i in range(20):
+ tk.Label(frame2, text="Label "+str(i)).pack(side=tk.LEFT)
- canvas2.create_window(0, 0, window=frame2, anchor='nw')
+ canvas2.create_window(0, 0, window=frame2, anchor='nw')
- canvas2.update_idletasks()
- canvas2['scrollregion'] = (0,0,frame2.winfo_reqwidth(), frame2.winfo_reqheight())
+ canvas2.update_idletasks()
+ canvas2['scrollregion'] = (0,0,frame2.winfo_reqwidth(), frame2.winfo_reqheight())
- scrollbar.add_ScrollableArea(canvas1,canvas2)
+ scrollbar.add_ScrollableArea(canvas1,canvas2)
- MouseWheel(root).add_scrolling(canvas1, xscrollbar=scrollbar)
- MouseWheel(root).add_scrolling(canvas2, xscrollbar=scrollbar)
+ MouseWheel(root).add_scrolling(canvas1, xscrollbar=scrollbar)
+ MouseWheel(root).add_scrolling(canvas2, xscrollbar=scrollbar)
- root.mainloop()
+ root.mainloop()
if __name__== '__main__':
- test()
+ test()