import Tkinter as tk class simultaneousScrollbar(tk.Scrollbar): def __init__(self, master, **kwargs): self.__scrollableWidgets = [] self.orientLabel = 'y' 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.") kwargs['command'] = command=self.onScroll tk.Scrollbar.__init__(self, master, **kwargs) self.scrollbarClicked = False self.mouseOver = False self.bind_all("<1>", self.onClickOnWindow) self.bind_all("<MouseWheel>", self.onMouseWheel) self.bind("<4>", self.onMouseWheel) self.bind("<5>", self.onMouseWheel) self.bind("<Enter>", self.onMouseOver) self.bind("<Leave>", self.onMouseOut) def add_ScrollableZones(self, *scrollableWidgets): for widget in scrollableWidgets: self.__scrollableWidgets.append(widget) widget[self.orientLabel+'scrollcommand']=self.set widget.bind("<MouseWheel>", self.onMouseWheel) def onScroll(self, *args): for widget in self.__scrollableWidgets: getattr(widget, self.orientLabel+'view')(*args) def onClickOnWindow(self,event): if self.winfo_containing(event.x_root, event.y_root) == self: self.scrollbarClicked = True else: self.scrollbarClicked = False def onMouseOver(self,event): self.mouseOver = True def onMouseOut(self,event): self.mouseOver = False def onMouseWheel(self, event): if self.scrollbarClicked: mouseWheel = True else: if self.mouseOver: mouseWheel = True else: mouseWheel = False if mouseWheel: for widget in self.__scrollableWidgets: getattr(widget, self.orientLabel+'view')("scroll", (-1)*event.delta/120,"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_ScrollableZones(canvas1,canvas2) root.mainloop() if __name__== '__main__': test()