chrisheinze
chrisheinze

Reputation: 1189

tkinter Scrollbar collapses the Canvas it's in

I'm attempting to make a program with two sections. The left section will display a vertically scrollable list while the right section will display info based on the items selected in the list. Ignore the right section since I haven't gotten there yet.

Below is a general idea of what it'll look like except the left section will scroll vertically.

enter image description here

Unfortunately when I pack the scrollbar the left section completely disappears.

enter image description here

Below is the code.

import tkinter as tk


class Tasks(tk.Tk):
    def __init__(self, builds=None):
        super().__init__()

        if builds is None:
            self.builds = []
        else:
            self.builds = builds

        self.title('Title')
        self.geometry('1000x600')
        self.configure(bg='red')

        self.tasks_canvas = tk.Canvas(self, width=200, bg='green')
        self.tasks_frame = tk.Frame(self.tasks_canvas)
        self.scrollbar = tk.Scrollbar(self.tasks_canvas, orient='vertical',command=self.tasks_canvas.yview)

        self.canvas_frame = self.tasks_canvas.create_window((0, 0), window=self.tasks_frame, anchor='n')

        self.tasks_canvas.configure(yscrollcommand=self.scrollbar.set)

        self.tasks_canvas.pack(side=tk.LEFT, fill=tk.Y)
        self.scrollbar.pack(side=tk.LEFT, fill=tk.Y, expand=1)


if __name__ == '__main__':
    root = Tasks()
    root.mainloop()

I'm sure I'm missing a simply concept but I just can't figure it out.

Upvotes: 2

Views: 136

Answers (1)

Miraj50
Miraj50

Reputation: 4407

The reason this is happening is because of the way pack geometry manager works. Have a look at this answer. Quoting it here:

By default pack will attempt to shrink (or grow) a container to exactly fit its children. Because the scrollbar is a children of the canvas in the, the canvas shrinks to fit.

To get around this, you can use an extra Frame to contain the Canvas and the Scrollbar and set the parent of the Scrollbar as this Frame.

import tkinter as tk

class Tasks(tk.Tk):
    def __init__(self, builds=None):
        super().__init__()

        self.title('Title')
        self.geometry('400x120')
        self.configure(bg='red')

        self.t_frame = tk.Frame(self)
        self.t_frame.pack(side=tk.LEFT)
        self.tasks_canvas = tk.Canvas(self.t_frame, width=100, bg='green')
        self.scrollbar = tk.Scrollbar(self.t_frame, orient='vertical',command=self.tasks_canvas.yview)

        self.tasks_canvas.configure(yscrollcommand=self.scrollbar.set)

        self.tasks_canvas.pack(side=tk.LEFT, fill=tk.Y)
        self.scrollbar.pack(side=tk.LEFT, fill=tk.Y)

if __name__ == '__main__':
    root = Tasks()
    root.mainloop()

Result

Upvotes: 1

Related Questions