Advertisement
ALEXANDAR_GEORGIEV

scrollbar_frame

Nov 26th, 2022
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.84 KB | Source Code | 0 0
  1. import tkinter as tk  # python 3
  2. from tkinter import font as tkfont  # python 3
  3.  
  4.  
  5. class SampleApp(tk.Tk):
  6.  
  7.     def __init__(self, *args, **kwargs):
  8.         tk.Tk.__init__(self, *args, **kwargs)
  9.  
  10.         self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")
  11.  
  12.         container = tk.Frame(self)
  13.         container.pack(side="top", fill="both", expand=True)
  14.         container.grid_rowconfigure(0, weight=1)
  15.         container.grid_columnconfigure(0, weight=1)
  16.  
  17.         scrollable_frame = ScrollableFrame(container, bg="red")
  18.         scrollable_frame.pack(fill="both", expand=True)
  19.  
  20.         scrollable_frame.grid_rowconfigure(0, weight=1)
  21.         scrollable_frame.grid_columnconfigure(0, weight=1)
  22.  
  23.         self.frames = {}
  24.         for F in (StartPage, PageOne, PageTwo):
  25.             page_name = F.__name__
  26.             frame = F(parent=scrollable_frame, controller=self)
  27.             self.frames[page_name] = frame
  28.  
  29.             # put all of the pages in the same location;
  30.             # the one on the top of the stacking order
  31.             # will be the one that is visible.
  32.             frame.grid(row=0, column=0, sticky="nsew")
  33.             frame.grid_rowconfigure(0, weight=1)
  34.             frame.grid_columnconfigure(0, weight=1)
  35.             frame.config(highlightbackground="green", highlightcolor="green", highlightthickness=1)
  36.  
  37.         self.show_frame("StartPage")
  38.  
  39.     def show_frame(self, page_name):
  40.         # Show a frame for the given page name
  41.         frame = self.frames[page_name]
  42.         frame.tkraise()
  43.  
  44.     FIT_WIDTH = "fit_width"
  45.     FIT_HEIGHT = "fit_height"
  46.  
  47.  
  48. class ScrollableFrame(tk.Frame):
  49.     """
  50.   There is no way to scroll <tkinter.Frame> so we are
  51.   going to create a canvas and place the frame there.
  52.   Scrolling the canvas will give the illution of scrolling
  53.   the frame
  54.   Partly taken from:
  55.       https://blog.tecladocode.com/tkinter-scrollable-frames/
  56.       https://stackoverflow.com/a/17457843/11106801
  57.  
  58.   master_frame---------------------------------------------------------
  59.   | dummy_canvas-----------------------------------------  y_scroll--  |
  60.   | | self---------------------------------------------  | |         | |
  61.   | | |                                                | | |         | |
  62.   | | |                                                | | |         | |
  63.   | | |                                                | | |         | |
  64.   | |  ------------------------------------------------  | |         | |
  65.   |  ----------------------------------------------------  |         | |
  66.   |                                                        |         | |
  67.   | x_scroll---------------------------------------------  |         | |
  68.   | |                                                    | |         | |
  69.   |  ----------------------------------------------------   ---------  |
  70.    --------------------------------------------------------------------
  71.   """
  72.  
  73.     def __init__(self, master=None, scroll_speed=2,
  74.                  hscroll=False, vscroll=True, **kwargs):
  75.         assert isinstance(scroll_speed, int), "`scroll_speed` must be an int"
  76.         self.scroll_speed = scroll_speed
  77.  
  78.         self.master_frame = tk.Frame(master)
  79.         self.dummy_canvas = tk.Canvas(self.master_frame, **kwargs)
  80.         super().__init__(self.dummy_canvas)
  81.  
  82.         # Create the 2 scrollbars
  83.         if vscroll:
  84.             self.v_scrollbar = tk.Scrollbar(self.master_frame,
  85.                                             orient="vertical",
  86.                                             command=self.dummy_canvas.yview)
  87.             self.v_scrollbar.pack(side="right", fill="y")
  88.             self.dummy_canvas.configure(yscrollcommand=self.v_scrollbar.set)
  89.         if hscroll:
  90.             self.h_scrollbar = tk.Scrollbar(self.master_frame,
  91.                                             orient="horizontal",
  92.                                             command=self.dummy_canvas.xview)
  93.             self.h_scrollbar.pack(side="bottom", fill="x")
  94.             self.dummy_canvas.configure(xscrollcommand=self.h_scrollbar.set)
  95.  
  96.         # Bind to the mousewheel scrolling
  97.         self.dummy_canvas.bind_all("<MouseWheel>", self.scrolling_windows,
  98.                                    add=True)
  99.         self.dummy_canvas.bind_all("<Button-4>", self.scrolling_linux, add=True)
  100.         self.dummy_canvas.bind_all("<Button-5>", self.scrolling_linux, add=True)
  101.         self.bind("<Configure>", self.scrollbar_scrolling, add=True)
  102.  
  103.         # Place `self` inside `dummy_canvas`
  104.         self.dummy_canvas.create_window((0, 0), window=self, anchor="nw")
  105.         # Place `dummy_canvas` inside `master_frame`
  106.         self.dummy_canvas.pack(side="top", expand=True, fill="both")
  107.  
  108.         self.pack = self.master_frame.pack
  109.         self.grid = self.master_frame.grid
  110.         self.place = self.master_frame.place
  111.         self.pack_forget = self.master_frame.pack_forget
  112.         self.grid_forget = self.master_frame.grid_forget
  113.         self.place_forget = self.master_frame.place_forget
  114.  
  115.     def scrolling_windows(self, event):
  116.         assert event.delta != 0, "On Windows, `event.delta` should never be 0"
  117.         y_steps = int(-event.delta / abs(event.delta) * self.scroll_speed)
  118.         self.dummy_canvas.yview_scroll(y_steps, "units")
  119.  
  120.     def scrolling_linux(self, event):
  121.         y_steps = self.scroll_speed
  122.         if event.num == 4:
  123.             y_steps *= -1
  124.         self.dummy_canvas.yview_scroll(y_steps, "units")
  125.  
  126.     def scrollbar_scrolling(self, event):
  127.         region = list(self.dummy_canvas.bbox("all"))
  128.         region[2] = max(self.dummy_canvas.winfo_width(), region[2])
  129.         region[3] = max(self.dummy_canvas.winfo_height(), region[3])
  130.         self.dummy_canvas.configure(scrollregion=region)
  131.  
  132.     def resize(self, fit=None, height=None, width=None):
  133.         if fit == FIT_WIDTH:
  134.             super().update()
  135.             self.dummy_canvas.config(width=super().winfo_width())
  136.         if fit == FIT_HEIGHT:
  137.             super().update()
  138.             self.dummy_canvas.config(height=super().winfo_height())
  139.         if height is not None:
  140.             self.dummy_canvas.config(height=height)
  141.         if width is not None:
  142.             self.dummy_canvas.config(width=width)
  143.  
  144.     fit = resize
  145.  
  146.  
  147. class StartPage(tk.Frame):
  148.  
  149.     def __init__(self, parent, controller):
  150.         tk.Frame.__init__(self, parent)
  151.         self.controller = controller
  152.         label = tk.Label(self, text="This is the start page", font=controller.title_font)
  153.         label.pack(side="top", fill="x", pady=10)
  154.  
  155.         button1 = tk.Button(self, text="Go to Page One",
  156.                             command=lambda: controller.show_frame("PageOne"))
  157.         button2 = tk.Button(self, text="Go to Page Two",
  158.                             command=lambda: controller.show_frame("PageTwo"))
  159.         button1.pack()
  160.         button2.pack()
  161.  
  162.  
  163. class PageOne(tk.Frame):
  164.  
  165.     def __init__(self, parent, controller):
  166.         tk.Frame.__init__(self, parent)
  167.         self.controller = controller
  168.         label = tk.Label(self, text="This is page 1", font=controller.title_font)
  169.         label.pack(side="top", fill="x", pady=10)
  170.         for i in range(0, 99):
  171.             button = tk.Button(self, text="Go to the start page",
  172.                                command=lambda: controller.show_frame("StartPage"))
  173.             button.pack()
  174.  
  175.  
  176. class PageTwo(tk.Frame):
  177.  
  178.     def __init__(self, parent, controller):
  179.         tk.Frame.__init__(self, parent)
  180.         self.controller = controller
  181.         label = tk.Label(self, text="This is page 2", font=controller.title_font)
  182.         label.pack(side="top", fill="x", pady=10)
  183.         button = tk.Button(self, text="Go to the start page",
  184.                            command=lambda: controller.show_frame("StartPage"))
  185.         button.pack()
  186.  
  187.  
  188. if __name__ == "__main__":
  189.     app = SampleApp()
  190.     app.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement