#!/usr/bin/python
# -*- coding: utf-8 -*-

#created by EugeneBakin 2016
#github link https://gist.github.com/EugeneBakin/76c8f9bcec5b390e45df

from tkinter import *   # from x import * is bad practice
from tkinter.ttk import *

# http://tkinter.unpythonic.net/wiki/VerticalScrolledFrame

class VerticalScrolledFrame(Frame):
    """A pure Tkinter scrollable frame that actually works!
    * Use the 'interior' attribute to place widgets inside the scrollable frame
    * Construct and pack/place/grid normally
    * This frame only allows vertical scrolling
    """
    def __init__(self, parent, *args, **kw):
        Frame.__init__(self, parent, *args, **kw)            

        # create a canvas object and a vertical scrollbar for scrolling it
        vscrollbar = Scrollbar(self, orient=VERTICAL)
        vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)
        canvas = Canvas(self, bd=0, highlightthickness=0, yscrollcommand=vscrollbar.set)
        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
        vscrollbar.config(command=canvas.yview)

        # reset the view
        canvas.xview_moveto(0)
        canvas.yview_moveto(0)

        # create a frame inside the canvas which will be scrolled with it
        self.interior = interior = Frame(canvas)
        interior_id = canvas.create_window(0, 0, window=interior, anchor=NW)

        # track changes to the canvas and frame width and sync them,
        # also updating the scrollbar
        def _configure_interior(event):
            # update the scrollbars to match the size of the inner frame
            size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
            canvas.config(scrollregion="0 0 %s %s" % size)
            if interior.winfo_reqwidth() != canvas.winfo_width():
                # update the canvas's width to fit the inner frame
                canvas.config(width=interior.winfo_reqwidth())
        interior.bind('<Configure>', _configure_interior)

        def _configure_canvas(event):
            if interior.winfo_reqwidth() != canvas.winfo_width():
                # update the inner frame's width to fill the canvas
                canvas.itemconfigure(interior_id, width=canvas.winfo_width())
        canvas.bind('<Configure>', _configure_canvas)
        def _on_mousewheel(event):
            canvas.yview_scroll(-1*int(event.delta/120), "units")
        canvas.bind("<MouseWheel>", _on_mousewheel)
#editions by Edmund King
class HorizontalScrolledFrame(Frame):
    """A pure Tkinter scrollable frame that actually works!
    * Use the 'interior' attribute to place widgets inside the scrollable frame
    * Construct and pack/place/grid normally
    * This frame only allows horizontal scrolling
    """

    def __init__(self, parent, *args, **kw):
        Frame.__init__(self, parent, *args, **kw)

        # create a canvas object and a horizontal scrollbar for scrolling it
        hscrollbar = Scrollbar(self, orient=HORIZONTAL)
        hscrollbar.pack(fill=X, side=BOTTOM, expand=FALSE)
        canvas = Canvas(self, bd=0, highlightthickness=0,
                        xscrollcommand=hscrollbar.set)
        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
        hscrollbar.config(command=canvas.xview)

        # reset the view
        canvas.xview_moveto(0)
        canvas.yview_moveto(0)
         # create a frame inside the canvas which will be scrolled with it
        self.interior = interior = Frame(canvas)
        interior_id = canvas.create_window(0, 0, window=interior, anchor=NW)

        # track changes to the canvas and frame width and sync them,
        # also updating the scrollbar
        def _configure_interior(event):
            # update the scrollbars to match the size of the inner frame
            size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
            canvas.config(scrollregion="0 0 %s %s" % size)
            if interior.winfo_reqheight() != canvas.winfo_height():
                # update the canvas's width to fit the inner frame
                canvas.config(width=interior.winfo_reqheight())
        interior.bind('<Configure>', _configure_interior)

        def _configure_canvas(event):
            if interior.winfo_reqheight != canvas.winfo_height():
                # update the inner frame's width to fill the canvas
                canvas.itemconfigure(interior_id, width=canvas.winfo_width())
        canvas.bind('<Configure>', _configure_canvas)
class TwoDimScrolledFrame(Frame):
    def __init__(self, parent, *args, **kw):
        Frame.__init__(self, parent, *args, **kw)

        # create a canvas object and a horizontal and vertical scrollbar for scrolling it
        hscrollbar = Scrollbar(self, orient=HORIZONTAL)
        hscrollbar.pack(fill=X, side=BOTTOM, expand=FALSE)

        vscrollbar = Scrollbar(self, orient=VERTICAL)
        vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)

        canvas = Canvas(self, bd=0, highlightthickness=0, yscrollcommand=vscrollbar.set, xscrollcommand=hscrollbar.set)
        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
        hscrollbar.config(command=canvas.xview)
        vscrollbar.config(command=canvas.yview)

        # reset the view
        canvas.xview_moveto(0)
        canvas.yview_moveto(0)

        # create a frame inside the canvas which will be scrolled with it
        self.interior = interior = Frame(canvas)
        canvas.create_window(0, 0, window=interior, anchor=NW)
        # track changes to the canvas and frame width and sync them,
        # also updating the scrollbar
        def _configure_interior(event):
            # update the scrollbars to match the size of the inner frame
            size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
            canvas.config(scrollregion="0 0 %s %s" % size)
        interior.bind('<Configure>', _configure_interior)

        self.lastmousepos = []
        def _on_mousewheel(event):
            canvas.yview_scroll(-1*int(event.delta/120), "units")
        canvas.bind_all("<MouseWheel>", _on_mousewheel)
        def _on_mouse2drag(event):
            if self.lastmousepos:
                xdiff = int(event.x) - self.lastmousepos[0]
                xdiff = max(-1, min(xdiff, 1))
                ydiff = int(event.y) - self.lastmousepos[1]
                ydiff = max(-1, min(ydiff, 1))
                canvas.xview_scroll(xdiff, "units")
                canvas.yview_scroll(ydiff, "units")
                self.lastmousepos = []
            else:
                self.lastmousepos = [int(event.x), int(event.y)]
        def _on_mouse2release(event):
            self.lastmousepos = []
        canvas.bind_all("<B2-Motion>", _on_mouse2drag)
        canvas.bind_all("<ButtonRelease-2>", _on_mouse2release)

cc73fcb95c7390032b71db1b9ee23b8a0ce5c280
<mask token>


class HorizontalScrolledFrame(Frame):
    """A pure Tkinter scrollable frame that actually works!
    * Use the 'interior' attribute to place widgets inside the scrollable frame
    * Construct and pack/place/grid normally
    * This frame only allows horizontal scrolling
    """

    def __init__(self, parent, *args, **kw):
        Frame.__init__(self, parent, *args, **kw)
        hscrollbar = Scrollbar(self, orient=HORIZONTAL)
        hscrollbar.pack(fill=X, side=BOTTOM, expand=FALSE)
        canvas = Canvas(self, bd=0, highlightthickness=0, xscrollcommand=
            hscrollbar.set)
        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
        hscrollbar.config(command=canvas.xview)
        canvas.xview_moveto(0)
        canvas.yview_moveto(0)
        self.interior = interior = Frame(canvas)
        interior_id = canvas.create_window(0, 0, window=interior, anchor=NW)

        def _configure_interior(event):
            size = interior.winfo_reqwidth(), interior.winfo_reqheight()
            canvas.config(scrollregion='0 0 %s %s' % size)
            if interior.winfo_reqheight() != canvas.winfo_height():
                canvas.config(width=interior.winfo_reqheight())
        interior.bind('<Configure>', _configure_interior)

        def _configure_canvas(event):
            if interior.winfo_reqheight != canvas.winfo_height():
                canvas.itemconfigure(interior_id, width=canvas.winfo_width())
        canvas.bind('<Configure>', _configure_canvas)


class TwoDimScrolledFrame(Frame):

    def __init__(self, parent, *args, **kw):
        Frame.__init__(self, parent, *args, **kw)
        hscrollbar = Scrollbar(self, orient=HORIZONTAL)
        hscrollbar.pack(fill=X, side=BOTTOM, expand=FALSE)
        vscrollbar = Scrollbar(self, orient=VERTICAL)
        vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)
        canvas = Canvas(self, bd=0, highlightthickness=0, yscrollcommand=
            vscrollbar.set, xscrollcommand=hscrollbar.set)
        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
        hscrollbar.config(command=canvas.xview)
        vscrollbar.config(command=canvas.yview)
        canvas.xview_moveto(0)
        canvas.yview_moveto(0)
        self.interior = interior = Frame(canvas)
        canvas.create_window(0, 0, window=interior, anchor=NW)

        def _configure_interior(event):
            size = interior.winfo_reqwidth(), interior.winfo_reqheight()
            canvas.config(scrollregion='0 0 %s %s' % size)
        interior.bind('<Configure>', _configure_interior)
        self.lastmousepos = []

        def _on_mousewheel(event):
            canvas.yview_scroll(-1 * int(event.delta / 120), 'units')
        canvas.bind_all('<MouseWheel>', _on_mousewheel)

        def _on_mouse2drag(event):
            if self.lastmousepos:
                xdiff = int(event.x) - self.lastmousepos[0]
                xdiff = max(-1, min(xdiff, 1))
                ydiff = int(event.y) - self.lastmousepos[1]
                ydiff = max(-1, min(ydiff, 1))
                canvas.xview_scroll(xdiff, 'units')
                canvas.yview_scroll(ydiff, 'units')
                self.lastmousepos = []
            else:
                self.lastmousepos = [int(event.x), int(event.y)]

        def _on_mouse2release(event):
            self.lastmousepos = []
        canvas.bind_all('<B2-Motion>', _on_mouse2drag)
        canvas.bind_all('<ButtonRelease-2>', _on_mouse2release)

<mask token>


class VerticalScrolledFrame(Frame):
    <mask token>
    <mask token>


class HorizontalScrolledFrame(Frame):
    """A pure Tkinter scrollable frame that actually works!
    * Use the 'interior' attribute to place widgets inside the scrollable frame
    * Construct and pack/place/grid normally
    * This frame only allows horizontal scrolling
    """

    def __init__(self, parent, *args, **kw):
        Frame.__init__(self, parent, *args, **kw)
        hscrollbar = Scrollbar(self, orient=HORIZONTAL)
        hscrollbar.pack(fill=X, side=BOTTOM, expand=FALSE)
        canvas = Canvas(self, bd=0, highlightthickness=0, xscrollcommand=
            hscrollbar.set)
        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
        hscrollbar.config(command=canvas.xview)
        canvas.xview_moveto(0)
        canvas.yview_moveto(0)
        self.interior = interior = Frame(canvas)
        interior_id = canvas.create_window(0, 0, window=interior, anchor=NW)

        def _configure_interior(event):
            size = interior.winfo_reqwidth(), interior.winfo_reqheight()
            canvas.config(scrollregion='0 0 %s %s' % size)
            if interior.winfo_reqheight() != canvas.winfo_height():
                canvas.config(width=interior.winfo_reqheight())
        interior.bind('<Configure>', _configure_interior)

        def _configure_canvas(event):
            if interior.winfo_reqheight != canvas.winfo_height():
                canvas.itemconfigure(interior_id, width=canvas.winfo_width())
        canvas.bind('<Configure>', _configure_canvas)


class TwoDimScrolledFrame(Frame):

    def __init__(self, parent, *args, **kw):
        Frame.__init__(self, parent, *args, **kw)
        hscrollbar = Scrollbar(self, orient=HORIZONTAL)
        hscrollbar.pack(fill=X, side=BOTTOM, expand=FALSE)
        vscrollbar = Scrollbar(self, orient=VERTICAL)
        vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)
        canvas = Canvas(self, bd=0, highlightthickness=0, yscrollcommand=
            vscrollbar.set, xscrollcommand=hscrollbar.set)
        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
        hscrollbar.config(command=canvas.xview)
        vscrollbar.config(command=canvas.yview)
        canvas.xview_moveto(0)
        canvas.yview_moveto(0)
        self.interior = interior = Frame(canvas)
        canvas.create_window(0, 0, window=interior, anchor=NW)

        def _configure_interior(event):
            size = interior.winfo_reqwidth(), interior.winfo_reqheight()
            canvas.config(scrollregion='0 0 %s %s' % size)
        interior.bind('<Configure>', _configure_interior)
        self.lastmousepos = []

        def _on_mousewheel(event):
            canvas.yview_scroll(-1 * int(event.delta / 120), 'units')
        canvas.bind_all('<MouseWheel>', _on_mousewheel)

        def _on_mouse2drag(event):
            if self.lastmousepos:
                xdiff = int(event.x) - self.lastmousepos[0]
                xdiff = max(-1, min(xdiff, 1))
                ydiff = int(event.y) - self.lastmousepos[1]
                ydiff = max(-1, min(ydiff, 1))
                canvas.xview_scroll(xdiff, 'units')
                canvas.yview_scroll(ydiff, 'units')
                self.lastmousepos = []
            else:
                self.lastmousepos = [int(event.x), int(event.y)]

        def _on_mouse2release(event):
            self.lastmousepos = []
        canvas.bind_all('<B2-Motion>', _on_mouse2drag)
        canvas.bind_all('<ButtonRelease-2>', _on_mouse2release)

<mask token>


class VerticalScrolledFrame(Frame):
    <mask token>

    def __init__(self, parent, *args, **kw):
        Frame.__init__(self, parent, *args, **kw)
        vscrollbar = Scrollbar(self, orient=VERTICAL)
        vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)
        canvas = Canvas(self, bd=0, highlightthickness=0, yscrollcommand=
            vscrollbar.set)
        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
        vscrollbar.config(command=canvas.yview)
        canvas.xview_moveto(0)
        canvas.yview_moveto(0)
        self.interior = interior = Frame(canvas)
        interior_id = canvas.create_window(0, 0, window=interior, anchor=NW)

        def _configure_interior(event):
            size = interior.winfo_reqwidth(), interior.winfo_reqheight()
            canvas.config(scrollregion='0 0 %s %s' % size)
            if interior.winfo_reqwidth() != canvas.winfo_width():
                canvas.config(width=interior.winfo_reqwidth())
        interior.bind('<Configure>', _configure_interior)

        def _configure_canvas(event):
            if interior.winfo_reqwidth() != canvas.winfo_width():
                canvas.itemconfigure(interior_id, width=canvas.winfo_width())
        canvas.bind('<Configure>', _configure_canvas)

        def _on_mousewheel(event):
            canvas.yview_scroll(-1 * int(event.delta / 120), 'units')
        canvas.bind('<MouseWheel>', _on_mousewheel)


class HorizontalScrolledFrame(Frame):
    """A pure Tkinter scrollable frame that actually works!
    * Use the 'interior' attribute to place widgets inside the scrollable frame
    * Construct and pack/place/grid normally
    * This frame only allows horizontal scrolling
    """

    def __init__(self, parent, *args, **kw):
        Frame.__init__(self, parent, *args, **kw)
        hscrollbar = Scrollbar(self, orient=HORIZONTAL)
        hscrollbar.pack(fill=X, side=BOTTOM, expand=FALSE)
        canvas = Canvas(self, bd=0, highlightthickness=0, xscrollcommand=
            hscrollbar.set)
        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
        hscrollbar.config(command=canvas.xview)
        canvas.xview_moveto(0)
        canvas.yview_moveto(0)
        self.interior = interior = Frame(canvas)
        interior_id = canvas.create_window(0, 0, window=interior, anchor=NW)

        def _configure_interior(event):
            size = interior.winfo_reqwidth(), interior.winfo_reqheight()
            canvas.config(scrollregion='0 0 %s %s' % size)
            if interior.winfo_reqheight() != canvas.winfo_height():
                canvas.config(width=interior.winfo_reqheight())
        interior.bind('<Configure>', _configure_interior)

        def _configure_canvas(event):
            if interior.winfo_reqheight != canvas.winfo_height():
                canvas.itemconfigure(interior_id, width=canvas.winfo_width())
        canvas.bind('<Configure>', _configure_canvas)


class TwoDimScrolledFrame(Frame):

    def __init__(self, parent, *args, **kw):
        Frame.__init__(self, parent, *args, **kw)
        hscrollbar = Scrollbar(self, orient=HORIZONTAL)
        hscrollbar.pack(fill=X, side=BOTTOM, expand=FALSE)
        vscrollbar = Scrollbar(self, orient=VERTICAL)
        vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)
        canvas = Canvas(self, bd=0, highlightthickness=0, yscrollcommand=
            vscrollbar.set, xscrollcommand=hscrollbar.set)
        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
        hscrollbar.config(command=canvas.xview)
        vscrollbar.config(command=canvas.yview)
        canvas.xview_moveto(0)
        canvas.yview_moveto(0)
        self.interior = interior = Frame(canvas)
        canvas.create_window(0, 0, window=interior, anchor=NW)

        def _configure_interior(event):
            size = interior.winfo_reqwidth(), interior.winfo_reqheight()
            canvas.config(scrollregion='0 0 %s %s' % size)
        interior.bind('<Configure>', _configure_interior)
        self.lastmousepos = []

        def _on_mousewheel(event):
            canvas.yview_scroll(-1 * int(event.delta / 120), 'units')
        canvas.bind_all('<MouseWheel>', _on_mousewheel)

        def _on_mouse2drag(event):
            if self.lastmousepos:
                xdiff = int(event.x) - self.lastmousepos[0]
                xdiff = max(-1, min(xdiff, 1))
                ydiff = int(event.y) - self.lastmousepos[1]
                ydiff = max(-1, min(ydiff, 1))
                canvas.xview_scroll(xdiff, 'units')
                canvas.yview_scroll(ydiff, 'units')
                self.lastmousepos = []
            else:
                self.lastmousepos = [int(event.x), int(event.y)]

        def _on_mouse2release(event):
            self.lastmousepos = []
        canvas.bind_all('<B2-Motion>', _on_mouse2drag)
        canvas.bind_all('<ButtonRelease-2>', _on_mouse2release)

<mask token>


class VerticalScrolledFrame(Frame):
    """A pure Tkinter scrollable frame that actually works!
    * Use the 'interior' attribute to place widgets inside the scrollable frame
    * Construct and pack/place/grid normally
    * This frame only allows vertical scrolling
    """

    def __init__(self, parent, *args, **kw):
        Frame.__init__(self, parent, *args, **kw)
        vscrollbar = Scrollbar(self, orient=VERTICAL)
        vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)
        canvas = Canvas(self, bd=0, highlightthickness=0, yscrollcommand=
            vscrollbar.set)
        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
        vscrollbar.config(command=canvas.yview)
        canvas.xview_moveto(0)
        canvas.yview_moveto(0)
        self.interior = interior = Frame(canvas)
        interior_id = canvas.create_window(0, 0, window=interior, anchor=NW)

        def _configure_interior(event):
            size = interior.winfo_reqwidth(), interior.winfo_reqheight()
            canvas.config(scrollregion='0 0 %s %s' % size)
            if interior.winfo_reqwidth() != canvas.winfo_width():
                canvas.config(width=interior.winfo_reqwidth())
        interior.bind('<Configure>', _configure_interior)

        def _configure_canvas(event):
            if interior.winfo_reqwidth() != canvas.winfo_width():
                canvas.itemconfigure(interior_id, width=canvas.winfo_width())
        canvas.bind('<Configure>', _configure_canvas)

        def _on_mousewheel(event):
            canvas.yview_scroll(-1 * int(event.delta / 120), 'units')
        canvas.bind('<MouseWheel>', _on_mousewheel)


class HorizontalScrolledFrame(Frame):
    """A pure Tkinter scrollable frame that actually works!
    * Use the 'interior' attribute to place widgets inside the scrollable frame
    * Construct and pack/place/grid normally
    * This frame only allows horizontal scrolling
    """

    def __init__(self, parent, *args, **kw):
        Frame.__init__(self, parent, *args, **kw)
        hscrollbar = Scrollbar(self, orient=HORIZONTAL)
        hscrollbar.pack(fill=X, side=BOTTOM, expand=FALSE)
        canvas = Canvas(self, bd=0, highlightthickness=0, xscrollcommand=
            hscrollbar.set)
        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
        hscrollbar.config(command=canvas.xview)
        canvas.xview_moveto(0)
        canvas.yview_moveto(0)
        self.interior = interior = Frame(canvas)
        interior_id = canvas.create_window(0, 0, window=interior, anchor=NW)

        def _configure_interior(event):
            size = interior.winfo_reqwidth(), interior.winfo_reqheight()
            canvas.config(scrollregion='0 0 %s %s' % size)
            if interior.winfo_reqheight() != canvas.winfo_height():
                canvas.config(width=interior.winfo_reqheight())
        interior.bind('<Configure>', _configure_interior)

        def _configure_canvas(event):
            if interior.winfo_reqheight != canvas.winfo_height():
                canvas.itemconfigure(interior_id, width=canvas.winfo_width())
        canvas.bind('<Configure>', _configure_canvas)


class TwoDimScrolledFrame(Frame):

    def __init__(self, parent, *args, **kw):
        Frame.__init__(self, parent, *args, **kw)
        hscrollbar = Scrollbar(self, orient=HORIZONTAL)
        hscrollbar.pack(fill=X, side=BOTTOM, expand=FALSE)
        vscrollbar = Scrollbar(self, orient=VERTICAL)
        vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)
        canvas = Canvas(self, bd=0, highlightthickness=0, yscrollcommand=
            vscrollbar.set, xscrollcommand=hscrollbar.set)
        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
        hscrollbar.config(command=canvas.xview)
        vscrollbar.config(command=canvas.yview)
        canvas.xview_moveto(0)
        canvas.yview_moveto(0)
        self.interior = interior = Frame(canvas)
        canvas.create_window(0, 0, window=interior, anchor=NW)

        def _configure_interior(event):
            size = interior.winfo_reqwidth(), interior.winfo_reqheight()
            canvas.config(scrollregion='0 0 %s %s' % size)
        interior.bind('<Configure>', _configure_interior)
        self.lastmousepos = []

        def _on_mousewheel(event):
            canvas.yview_scroll(-1 * int(event.delta / 120), 'units')
        canvas.bind_all('<MouseWheel>', _on_mousewheel)

        def _on_mouse2drag(event):
            if self.lastmousepos:
                xdiff = int(event.x) - self.lastmousepos[0]
                xdiff = max(-1, min(xdiff, 1))
                ydiff = int(event.y) - self.lastmousepos[1]
                ydiff = max(-1, min(ydiff, 1))
                canvas.xview_scroll(xdiff, 'units')
                canvas.yview_scroll(ydiff, 'units')
                self.lastmousepos = []
            else:
                self.lastmousepos = [int(event.x), int(event.y)]

        def _on_mouse2release(event):
            self.lastmousepos = []
        canvas.bind_all('<B2-Motion>', _on_mouse2drag)
        canvas.bind_all('<ButtonRelease-2>', _on_mouse2release)

#!/usr/bin/python
# -*- coding: utf-8 -*-

#created by EugeneBakin 2016
#github link https://gist.github.com/EugeneBakin/76c8f9bcec5b390e45df

from tkinter import *   # from x import * is bad practice
from tkinter.ttk import *

# http://tkinter.unpythonic.net/wiki/VerticalScrolledFrame

class VerticalScrolledFrame(Frame):
    """A pure Tkinter scrollable frame that actually works!
    * Use the 'interior' attribute to place widgets inside the scrollable frame
    * Construct and pack/place/grid normally
    * This frame only allows vertical scrolling
    """
    def __init__(self, parent, *args, **kw):
        Frame.__init__(self, parent, *args, **kw)            

        # create a canvas object and a vertical scrollbar for scrolling it
        vscrollbar = Scrollbar(self, orient=VERTICAL)
        vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)
        canvas = Canvas(self, bd=0, highlightthickness=0, yscrollcommand=vscrollbar.set)
        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
        vscrollbar.config(command=canvas.yview)

        # reset the view
        canvas.xview_moveto(0)
        canvas.yview_moveto(0)

        # create a frame inside the canvas which will be scrolled with it
        self.interior = interior = Frame(canvas)
        interior_id = canvas.create_window(0, 0, window=interior, anchor=NW)

        # track changes to the canvas and frame width and sync them,
        # also updating the scrollbar
        def _configure_interior(event):
            # update the scrollbars to match the size of the inner frame
            size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
            canvas.config(scrollregion="0 0 %s %s" % size)
            if interior.winfo_reqwidth() != canvas.winfo_width():
                # update the canvas's width to fit the inner frame
                canvas.config(width=interior.winfo_reqwidth())
        interior.bind('<Configure>', _configure_interior)

        def _configure_canvas(event):
            if interior.winfo_reqwidth() != canvas.winfo_width():
                # update the inner frame's width to fill the canvas
                canvas.itemconfigure(interior_id, width=canvas.winfo_width())
        canvas.bind('<Configure>', _configure_canvas)
        def _on_mousewheel(event):
            canvas.yview_scroll(-1*int(event.delta/120), "units")
        canvas.bind("<MouseWheel>", _on_mousewheel)
#editions by Edmund King
class HorizontalScrolledFrame(Frame):
    """A pure Tkinter scrollable frame that actually works!
    * Use the 'interior' attribute to place widgets inside the scrollable frame
    * Construct and pack/place/grid normally
    * This frame only allows horizontal scrolling
    """

    def __init__(self, parent, *args, **kw):
        Frame.__init__(self, parent, *args, **kw)

        # create a canvas object and a horizontal scrollbar for scrolling it
        hscrollbar = Scrollbar(self, orient=HORIZONTAL)
        hscrollbar.pack(fill=X, side=BOTTOM, expand=FALSE)
        canvas = Canvas(self, bd=0, highlightthickness=0,
                        xscrollcommand=hscrollbar.set)
        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
        hscrollbar.config(command=canvas.xview)

        # reset the view
        canvas.xview_moveto(0)
        canvas.yview_moveto(0)
         # create a frame inside the canvas which will be scrolled with it
        self.interior = interior = Frame(canvas)
        interior_id = canvas.create_window(0, 0, window=interior, anchor=NW)

        # track changes to the canvas and frame width and sync them,
        # also updating the scrollbar
        def _configure_interior(event):
            # update the scrollbars to match the size of the inner frame
            size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
            canvas.config(scrollregion="0 0 %s %s" % size)
            if interior.winfo_reqheight() != canvas.winfo_height():
                # update the canvas's width to fit the inner frame
                canvas.config(width=interior.winfo_reqheight())
        interior.bind('<Configure>', _configure_interior)

        def _configure_canvas(event):
            if interior.winfo_reqheight != canvas.winfo_height():
                # update the inner frame's width to fill the canvas
                canvas.itemconfigure(interior_id, width=canvas.winfo_width())
        canvas.bind('<Configure>', _configure_canvas)
class TwoDimScrolledFrame(Frame):
    def __init__(self, parent, *args, **kw):
        Frame.__init__(self, parent, *args, **kw)

        # create a canvas object and a horizontal and vertical scrollbar for scrolling it
        hscrollbar = Scrollbar(self, orient=HORIZONTAL)
        hscrollbar.pack(fill=X, side=BOTTOM, expand=FALSE)

        vscrollbar = Scrollbar(self, orient=VERTICAL)
        vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)

        canvas = Canvas(self, bd=0, highlightthickness=0, yscrollcommand=vscrollbar.set, xscrollcommand=hscrollbar.set)
        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
        hscrollbar.config(command=canvas.xview)
        vscrollbar.config(command=canvas.yview)

        # reset the view
        canvas.xview_moveto(0)
        canvas.yview_moveto(0)

        # create a frame inside the canvas which will be scrolled with it
        self.interior = interior = Frame(canvas)
        canvas.create_window(0, 0, window=interior, anchor=NW)
        # track changes to the canvas and frame width and sync them,
        # also updating the scrollbar
        def _configure_interior(event):
            # update the scrollbars to match the size of the inner frame
            size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
            canvas.config(scrollregion="0 0 %s %s" % size)
        interior.bind('<Configure>', _configure_interior)

        self.lastmousepos = []
        def _on_mousewheel(event):
            canvas.yview_scroll(-1*int(event.delta/120), "units")
        canvas.bind_all("<MouseWheel>", _on_mousewheel)
        def _on_mouse2drag(event):
            if self.lastmousepos:
                xdiff = int(event.x) - self.lastmousepos[0]
                xdiff = max(-1, min(xdiff, 1))
                ydiff = int(event.y) - self.lastmousepos[1]
                ydiff = max(-1, min(ydiff, 1))
                canvas.xview_scroll(xdiff, "units")
                canvas.yview_scroll(ydiff, "units")
                self.lastmousepos = []
            else:
                self.lastmousepos = [int(event.x), int(event.y)]
        def _on_mouse2release(event):
            self.lastmousepos = []
        canvas.bind_all("<B2-Motion>", _on_mouse2drag)
        canvas.bind_all("<ButtonRelease-2>", _on_mouse2release)
