DeAnna
DeAnna

Reputation: 402

Scrollbar in Tkinter Notebook frames

I cant get my scrollbar to show up correctly in my tkinter notebook. I need a scroll for each page

root = tk.Tk()
root.title('Client Intake Form')

n = ttk.Notebook(root)
f1 = ttk.Frame(n)
f2 = ttk.Frame(n)
f3 = ttk.Frame(n)
n.add(f1, text='Page 1', compound=tk.TOP)
n.add(f2, text='Page 2', compound=tk.TOP)
n.add(f3, text='Page 3', compound=tk.TOP)
n.pack()

canvas = tk.Canvas(f1, width=1000, height=1000, relief='raised')
canvas.pack()

scroll = tk.Scrollbar(canvas, command=canvas.yview, orient=tk.VERTICAL)
canvas.config(yscrollcommand=scroll.set, scrollregion=(1000,0,1000,1000))
scroll.pack(side=tk.RIGHT, fill=tk.Y, expand=True)

#######PAGE 2#######
page2 = tk.Canvas(f2, width=1000, height=1000, relief='raised')
page2.pack()

######PAGE 3######
page3 = tk.Canvas(f3, width=1000, height=1000, relief='raised')
page3.pack()

root.mainloop()

I want the scrollbar on the right side of each page.

Upvotes: 0

Views: 1514

Answers (1)

stovfl
stovfl

Reputation: 15513

Question: I cant get my scrollbar to show up correctly in my tkinter notebook.

  • I want the scrollbar on the right side of each page.
    Using the .pack manager is possible, but if you use the .grid manager instead, you get simpler laid out what you want.

  • I need a scroll for each page
    Instead of repeating yourself, define your own widget and reuse it on all your Notebook tabs.


  • Define a class YScrolledFrame by inheriting form (tk.Frame).
    This Frame grows as large as the parent widget allows.
    To behave the Scrollbar dynamic, you have to use .bind('<Configure>', ...

    class YScrolledFrame(tk.Frame):
        def __init__(self, parent, *args, **kwargs):
            super().__init__(parent, *args, **kwargs)
            self.grid_rowconfigure(0, weight=1)
            self.grid_columnconfigure(0, weight=1)
    
            self.canvas = canvas = tk.Canvas(self, bg='white', relief='raised')
            canvas.grid(row=0, column=0, sticky='nsew')
    
            scroll = tk.Scrollbar(self, command=canvas.yview, orient=tk.VERTICAL)
            canvas.config(yscrollcommand=scroll.set)
            scroll.grid(row=0, column=1, sticky='nsew')
    
            self.content = tk.Frame(canvas)
            self.canvas.create_window(0, 0, window=self.content, anchor="nw")
    
            self.bind('<Configure>', self.on_configure)
    
        def on_configure(self, event):
            bbox = self.content.bbox('ALL')
            self.canvas.config(scrollregion=bbox)
    
  • Define a class Notebook by inheriting form (ttk.Notebook).
    This allows to access a Notebook tab by it's label text.

    class Notebook(ttk.Notebook):
        def __init__(self, parent, tab_labels):
            super().__init__(parent)
    
            self._tab = {}
            for text in tab_labels:
                self._tab[text] = YScrolledFrame(self)
                # layout by .add defaults to fill=tk.BOTH, expand=True
                self.add(self._tab[text], text=text, compound=tk.TOP)
    
        def tab(self, key):
            return self._tab[key].content
    

Usage:

import tkinter as tk
import tkinter.ttk as ttk

class App(tk.Tk):
    def __init__(self):
        super().__init__()

        notebook = Notebook(self, ['Page 1', 'Page 2', 'Page 3'])
        notebook.grid(row=0, column=0, sticky='nsew')

        # Fill content, to see scroll action
        tab = notebook.tab('Page 1')
        for n in range(20):
            label = tk.Label(tab, text='Page 1 - Label {}'.format(n))
            label.grid()

if __name__ == '__main__':
    App().mainloop()

Tested with Python: 3.5

Upvotes: 1

Related Questions