0

I run an example about scrollbar based here. But I want to add a button (Prev) to frame and when scrollbar moves down, this button still stay there, while other content moves along with scrollbar.

enter image description here

Here is my code:

import Tkinter as tk

class Example(tk.Frame):
    def __init__(self, root):

        tk.Frame.__init__(self, root)
        self.canvas = tk.Canvas(root, borderwidth=0, background="#ffffff")
        self.frame = tk.Frame(self.canvas, background="#ffffff")
        self.vsb = tk.Scrollbar(root, orient="vertical", command=self.canvas.yview)
        self.canvas.configure(yscrollcommand=self.vsb.set)

        self.vsb.pack(side="right", fill="y")
        self.canvas.pack(side="left", fill="both", expand=True)
        self.canvas.create_window((4,4), window=self.frame, anchor="nw", tags="self.frame")

        self.frame.bind("<Configure>", self.onFrameConfigure)

        self.populate()

    def populate(self):

        button = tk.Button(self.frame, text='Prev')
        button.grid(row=0, columns=1)

        for row in range(1,100):
            tk.Label(self.frame, text="%s" % row, width=3, borderwidth="1", relief="solid").grid(row=row, column=0)
            t="this is the second column for row %s" %row
            tk.Label(self.frame, text=t).grid(row=row, column=1)

    def onFrameConfigure(self, event):
        '''Reset the scroll region to encompass the inner frame'''
        self.canvas.configure(scrollregion=self.canvas.bbox("all"))

if __name__ == "__main__":
    root=tk.Tk()
    Example(root).pack(side="top", fill="both", expand=True)
    root.mainloop()

Can anyone help me solve this problem? Many thanks!

Khang Truong
  • 357
  • 1
  • 6
  • 16

1 Answers1

1

You could do this with pack() as well but I prefer to use grid()

What you need to do is place the button in root on row 0 and place the class frame on row 1 of root. This should fix your problem.

When using grid() we need to manage the weights of the rows and columns so you get the growing and shrinking behavior when we resize the window. We can do this with rowconfigute() and columnconfigute(). For this program we need to configure the weights of root.

To get the button to stay at the left we can use sticky = "w" inside of grid() to chose the side to stick to.

Take a look at the below code:

import tkinter as tk

class Example(tk.Frame):
    def __init__(self, root):

        tk.Frame.__init__(self, root)
        self.canvas = tk.Canvas(root, borderwidth=0, background="#ffffff")
        self.frame = tk.Frame(self.canvas, background="#ffffff")
        self.vsb = tk.Scrollbar(root, orient="vertical", command=self.canvas.yview)
        self.canvas.configure(yscrollcommand=self.vsb.set)

        self.vsb.grid(row = 1, column = 1, sticky = "nsew")
        self.canvas.grid(row = 1, column = 0, sticky = "nsew")
        self.canvas.create_window((4,4), window=self.frame, anchor="nw", tags="self.frame")

        self.frame.bind("<Configure>", self.onFrameConfigure)

        self.populate()

    def populate(self):

        button = tk.Button(root, text='Prev')
        button.grid(row=0, columns=1, sticky = "w")

        for row in range(1,100):
            tk.Label(self.frame, text="%s" % row, width=3, borderwidth="1", relief="solid").grid(row=row, column=0)
            t="this is the second column for row %s" %row
            tk.Label(self.frame, text=t).grid(row=row, column=1)

    def onFrameConfigure(self, event):
        '''Reset the scroll region to encompass the inner frame'''
        self.canvas.configure(scrollregion=self.canvas.bbox("all"))

if __name__ == "__main__":
    root=tk.Tk()
    root.columnconfigure(0, weight = 1)
    root.rowconfigure(1, weight = 1)
    Example(root).grid(row = 1)
    root.mainloop()
Mike - SMT
  • 14,784
  • 4
  • 35
  • 79