import tkinter as tk from tkinter import ttk class ScrolledWindow(tk.Frame): """ 1. Master widget gets scrollbars and a canvas. Scrollbars are connected to canvas scrollregion. 2. self.scrollwindow is created and inserted into canvas Usage Guideline: Assign any widgets as children of .scrollwindow to get them inserted into canvas __init__(self, parent, canv_w = 400, canv_h = 400, *args, **kwargs) docstring: Parent = master of scrolled window canv_w - width of canvas canv_h - height of canvas """ def __init__(self, parent, canv_w = 400, canv_h = 400, *args, **kwargs): """Parent = master of scrolled window canv_w - width of canvas canv_h - height of canvas """ super().__init__(parent, *args, **kwargs) self.parent = parent # creating a scrollbars self.xscrlbr = ttk.Scrollbar(self.parent, orient = 'horizontal') self.xscrlbr.grid(column = 0, row = 1, sticky = 'ew', columnspan = 2) self.yscrlbr = ttk.Scrollbar(self.parent) self.yscrlbr.grid(column = 1, row = 0, sticky = 'ns') # creating a canvas self.canv = tk.Canvas(self.parent) self.canv.config(relief = 'flat', width = 10, heigh = 10, bd = 2) # placing a canvas into frame self.canv.grid(column = 0, row = 0, sticky = 'nsew') # accociating scrollbar comands to canvas scroling self.xscrlbr.config(command = self.canv.xview) self.yscrlbr.config(command = self.canv.yview) # creating a frame to inserto to canvas self.scrollwindow = ttk.Frame(self.parent) self.canv.create_window(0, 0, window = self.scrollwindow, anchor = 'nw') self.canv.config(xscrollcommand = self.xscrlbr.set, yscrollcommand = self.yscrlbr.set, scrollregion = (0, 0, 100, 100)) self.yscrlbr.lift(self.scrollwindow) self.xscrlbr.lift(self.scrollwindow) self.scrollwindow.bind('', self._configure_window) self.scrollwindow.bind('', self._bound_to_mousewheel) self.scrollwindow.bind('', self._unbound_to_mousewheel) return def _bound_to_mousewheel(self, event): self.canv.bind_all("", self._on_mousewheel) def _unbound_to_mousewheel(self, event): self.canv.unbind_all("") def _on_mousewheel(self, event): self.canv.yview_scroll(int(-1*(event.delta/120)), "units") def _configure_window(self, event): # update the scrollbars to match the size of the inner frame size = (self.scrollwindow.winfo_reqwidth(), self.scrollwindow.winfo_reqheight()) self.canv.config(scrollregion='0 0 %s %s' % size) if self.scrollwindow.winfo_reqwidth() != self.canv.winfo_width(): # update the canvas's width to fit the inner frame self.canv.config(width = self.scrollwindow.winfo_reqwidth()) if self.scrollwindow.winfo_reqheight() != self.canv.winfo_height(): # update the canvas's width to fit the inner frame self.canv.config(height = self.scrollwindow.winfo_reqheight()) if __name__ == "__main__": mainwindow = tk.Tk() s = ScrolledWindow(mainwindow) s.grid(row=0, column=0) tk.Label(s.scrollwindow, text="a").pack() mainwindow.mainloop()