Welcome, guest | Sign In | My Account | Store | Cart
# Version: 0.22
# Author: Miguel Martinez Lopez
# Uncomment the next line to see my email
# print("Author's email: ", "61706c69636163696f6e616d656469646140676d61696c2e636f6d".decode("hex"))

try:
   
from Tkinter import Canvas, Frame
   
from ttk import Scrollbar
   
   
from Tkconstants import *
except ImportError:
   
from tkinter import Canvas, Frame
   
from tkinter.ttk import Scrollbar
   
   
from tkinter.constants import *

import platform

OS
= platform.system()

class Mousewheel_Support(object):    

   
# implemetation of singleton pattern
    _instance
= None
   
def __new__(cls, *args, **kwargs):
       
if not cls._instance:
            cls
._instance = object.__new__(cls)
       
return cls._instance

   
def __init__(self, root, horizontal_factor = 2, vertical_factor=2):
       
       
self._active_area = None
       
       
if isinstance(horizontal_factor, int):
           
self.horizontal_factor = horizontal_factor
       
else:
           
raise Exception("Vertical factor must be an integer.")

       
if isinstance(vertical_factor, int):
           
self.vertical_factor = vertical_factor
       
else:
           
raise Exception("Horizontal factor must be an integer.")

       
if OS == "Linux" :
            root
.bind_all('<4>', self._on_mousewheel,  add='+')
            root
.bind_all('<5>', self._on_mousewheel,  add='+')
       
else:
           
# Windows and MacOS
            root
.bind_all("<MouseWheel>", self._on_mousewheel,  add='+')

   
def _on_mousewheel(self,event):
       
if self._active_area:
           
self._active_area.onMouseWheel(event)

   
def _mousewheel_bind(self, widget):
       
self._active_area = widget

   
def _mousewheel_unbind(self):
       
self._active_area = None

   
def add_support_to(self, widget=None, xscrollbar=None, yscrollbar=None, what="units", horizontal_factor=None, vertical_factor=None):
       
if xscrollbar is None and yscrollbar is None:
           
return

       
if xscrollbar is not None:
            horizontal_factor
= horizontal_factor or self.horizontal_factor

            xscrollbar
.onMouseWheel = self._make_mouse_wheel_handler(widget,'x', self.horizontal_factor, what)
            xscrollbar
.bind('<Enter>', lambda event, scrollbar=xscrollbar: self._mousewheel_bind(scrollbar) )
            xscrollbar
.bind('<Leave>', lambda event: self._mousewheel_unbind())

       
if yscrollbar is not None:
            vertical_factor
= vertical_factor or self.vertical_factor

            yscrollbar
.onMouseWheel = self._make_mouse_wheel_handler(widget,'y', self.vertical_factor, what)
            yscrollbar
.bind('<Enter>', lambda event, scrollbar=yscrollbar: self._mousewheel_bind(scrollbar) )
            yscrollbar
.bind('<Leave>', lambda event: self._mousewheel_unbind())

        main_scrollbar
= yscrollbar if yscrollbar is not None else xscrollbar
       
       
if widget is not None:
           
if isinstance(widget, list) or isinstance(widget, tuple):
                list_of_widgets
= widget
               
for widget in list_of_widgets:
                    widget
.bind('<Enter>',lambda event: self._mousewheel_bind(widget))
                    widget
.bind('<Leave>', lambda event: self._mousewheel_unbind())

                    widget
.onMouseWheel = main_scrollbar.onMouseWheel
           
else:
                widget
.bind('<Enter>',lambda event: self._mousewheel_bind(widget))
                widget
.bind('<Leave>', lambda event: self._mousewheel_unbind())

                widget
.onMouseWheel = main_scrollbar.onMouseWheel

   
@staticmethod
   
def _make_mouse_wheel_handler(widget, orient, factor = 1, what="units"):
        view_command
= getattr(widget, orient+'view')
       
       
if OS == 'Linux':
           
def onMouseWheel(event):
               
if event.num == 4:
                    view_command
("scroll",(-1)*factor, what)
               
elif event.num == 5:
                    view_command
("scroll",factor, what)
               
       
elif OS == 'Windows':
           
def onMouseWheel(event):        
                view_command
("scroll",(-1)*int((event.delta/120)*factor), what)
       
       
elif OS == 'Darwin':
           
def onMouseWheel(event):        
                view_command
("scroll",event.delta, what)
       
       
return onMouseWheel

class Scrolling_Area(Frame, object):

   
def __init__(self, master, width=None, anchor=N, height=None, mousewheel_speed = 2, scroll_horizontally=True, xscrollbar=None, scroll_vertically=True, yscrollbar=None, background=None, inner_frame=Frame, **kw):
       
Frame.__init__(self, master, class_="Scrolling_Area", background=background)

       
self.grid_columnconfigure(0, weight=1)
       
self.grid_rowconfigure(0, weight=1)
       
       
self._width = width
       
self._height = height

       
self.canvas = Canvas(self, background=background, highlightthickness=0, width=width, height=height)
       
self.canvas.grid(row=0, column=0, sticky=N+E+W+S)

       
if scroll_vertically:
           
if yscrollbar is not None:
               
self.yscrollbar = yscrollbar
           
else:
               
self.yscrollbar = Scrollbar(self, orient=VERTICAL)
               
self.yscrollbar.grid(row=0, column=1,sticky=N+S)
       
           
self.canvas.configure(yscrollcommand=self.yscrollbar.set)
           
self.yscrollbar['command']=self.canvas.yview
       
else:
           
self.yscrollbar = None

       
if scroll_horizontally:
           
if xscrollbar is not None:
               
self.xscrollbar = xscrollbar
           
else:
               
self.xscrollbar = Scrollbar(self, orient=HORIZONTAL)
               
self.xscrollbar.grid(row=1, column=0, sticky=E+W)
           
           
self.canvas.configure(xscrollcommand=self.xscrollbar.set)
           
self.xscrollbar['command']=self.canvas.xview
       
else:
           
self.xscrollbar = None

       
self.rowconfigure(0, weight=1)
       
self.columnconfigure(0, weight=1)
       
       
self.innerframe = inner_frame(self.canvas, **kw)
       
self.innerframe.pack(anchor=anchor)
       
       
self.canvas.create_window(0, 0, window=self.innerframe, anchor='nw', tags="inner_frame")

       
self.canvas.bind('<Configure>', self._on_canvas_configure)

       
Mousewheel_Support(self).add_support_to(self.canvas, xscrollbar=self.xscrollbar, yscrollbar=self.yscrollbar)

   
@property
   
def width(self):
       
return self.canvas.winfo_width()

   
@width.setter
   
def width(self, width):
       
self.canvas.configure(width= width)

   
@property
   
def height(self):
       
return self.canvas.winfo_height()
       
   
@height.setter
   
def height(self, height):
       
self.canvas.configure(height = height)
       
   
def set_size(self, width, height):
       
self.canvas.configure(width=width, height = height)

   
def _on_canvas_configure(self, event):
        width
= max(self.innerframe.winfo_reqwidth(), event.width)
        height
= max(self.innerframe.winfo_reqheight(), event.height)

       
self.canvas.configure(scrollregion="0 0 %s %s" % (width, height))
       
self.canvas.itemconfigure("inner_frame", width=width, height=height)

   
def update_viewport(self):
       
self.update()

        window_width
= self.innerframe.winfo_reqwidth()
        window_height
= self.innerframe.winfo_reqheight()
       
       
if self._width is None:
            canvas_width
= window_width
       
else:
            canvas_width
= min(self._width, window_width)
           
       
if self._height is None:
            canvas_height
= window_height
       
else:
            canvas_height
= min(self._height, window_height)

       
self.canvas.configure(scrollregion="0 0 %s %s" % (window_width, window_height), width=canvas_width, height=canvas_height)
       
self.canvas.itemconfigure("inner_frame", width=window_width, height=window_height)

if __name__== '__main__':
   
try:
       
from Tkinter import Tk, Label
   
except ImportError:
       
from tkinter import Tk, Label
   
    root
= Tk()
   
    scrolling_area
= Scrolling_Area(root)
    scrolling_area
.pack(expand=1, fill=BOTH)
   
   
for i in range(20):
        rowFrame
= Frame(scrolling_area.innerframe)
        rowFrame
.pack()
       
for j in range(8):
           
Label(rowFrame, text="Label %s, %s" % (str(i), str(j))).pack(side="left")

    root
.mainloop()

Diff to Previous Revision

--- revision 25 2017-05-06 18:53:25
+++ revision 26 2017-05-16 18:15:44
@@ -1,4 +1,4 @@
-# Version: 0.21
+# Version: 0.22
 
# Author: Miguel Martinez Lopez
 
# Uncomment the next line to see my email
 
# print("Author's email: ", "61706c69636163696f6e616d656469646140676d61696c2e636f6d".decode("hex"))
@@ -115,11 +115,8 @@
 
 
class Scrolling_Area(Frame, object):
 
-    def __init__(self, master, width=None, anchor=N, height=None, mousewheel_speed = 2, scroll_horizontally=True, xscrollbar=None, scroll_vertically=True, yscrollbar=None, outer_background=None, inner_frame=Frame, **kw):
-        Frame.__init__(self, master, class_=self.__class__)
-
-        if outer_background:
-            self.configure(background=outer_background)
+    def __init__(self, master, width=None, anchor=N, height=None, mousewheel_speed = 2, scroll_horizontally=True, xscrollbar=None, scroll_vertically=True, yscrollbar=None, background=None, inner_frame=Frame, **kw):
+        Frame.__init__(self, master, class_="Scrolling_Area", background=background)
 
         
self.grid_columnconfigure(0, weight=1)
         
self.grid_rowconfigure(0, weight=1)
@@ -127,7 +124,7 @@
         
self._width = width
         
self._height = height
 
-        self.canvas = Canvas(self, background=outer_background, highlightthickness=0, width=width, height=height)
+        self.canvas = Canvas(self, background=background, highlightthickness=0, width=width, height=height)
         
self.canvas.grid(row=0, column=0, sticky=N+E+W+S)
 
         
if scroll_vertically:

History