PushALU
PushALU

Reputation: 277

Tkinter, make scrollbar stick to canvas and not root?

I've got a working scrollbar and a canvas. Problem is that my canvas height and maybe even width are not the same dimensions as the root, but the scrollbar is attached to the root. Which looks odd. How can I make it stick to the canvas? So that I also may add an additional canvas with a scrollbar in the future.

        self.canvas = Canvas(root, borderwidth=0, background="#c0c0c0",height= 150, width=500)

        self.frameTwo = Frame(self.canvas, background="#ffffff")

        self.vsb = 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")
        self.canvas.place(y=195)
        self.canvas.create_window((4,4), window=self.frameTwo, anchor="w",
                                  tags="self.frame")

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

Upvotes: 1

Views: 543

Answers (1)

Bryan Oakley
Bryan Oakley

Reputation: 386020

The best solution is to put your scrollbars and canvas in a frame specifically for that purpose.

Here's a complete working example:

import tkinter as tk

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

        # create a frame specifically for the canvas,
        # and scrollbars, and let it control the border
        self.canvas_frame = tk.Frame(self, borderwidth = 1, relief="sunken")
        self.canvas = tk.Canvas(self.canvas_frame, borderwidth=0, highlightthickness=0,
                                background="white")
        self.vsb = tk.Scrollbar(self.canvas_frame, orient="vertical",
                                command=self.canvas.yview)
        self.hsb = tk.Scrollbar(self.canvas_frame, orient="horizontal",
                                command=self.canvas.xview)
        self.canvas.configure(yscrollcommand=self.vsb.set, 
                              xscrollcommand=self.hsb.set)

        self.canvas.grid(row=0, column=0, sticky="nsew")
        self.vsb.grid(row=0, column=1, sticky="ns")
        self.hsb.grid(row=1, column=0, sticky="ew")
        self.canvas_frame.rowconfigure(0, weight=1)
        self.canvas_frame.columnconfigure(0, weight=1)

        # add the canvas+scrollbars to the window
        self.canvas_frame.pack(fill="both", expand=True)

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

By the way, in your code you're calling both pack and place on the canvas. It's pointless to call both -- only one or the other can affect the placement of the widget. When you call place after calling pack for the same widget, the effects of calling place will be completely forgotten.

Upvotes: 0

Related Questions