Created
September 17, 2018 20:21
-
-
Save MikeTheWatchGuy/799493d7b42bf54b2b65765a60dc03ce to your computer and use it in GitHub Desktop.
TKinter scrollable frame
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# -*- coding: utf-8 -*- | |
from Tkinter import * # from x import * is bad practice | |
from 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) | |
if __name__ == "__main__": | |
class SampleApp(Tk): | |
def __init__(self, *args, **kwargs): | |
root = Tk.__init__(self, *args, **kwargs) | |
self.frame = VerticalScrolledFrame(root) | |
self.frame.pack() | |
self.label = Label(text="Shrink the window to activate the scrollbar.") | |
self.label.pack() | |
buttons = [] | |
for i in range(10): | |
buttons.append(Button(self.frame.interior, text="Button " + str(i))) | |
buttons[-1].pack() | |
app = SampleApp() | |
app.mainloop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment