Skip to content
Advertisement

How to make a scrollable listbox? tkinter python

I want to create a listbox with an auto hiding scrollbar. I’ve been searching and found a class example; when I play around with it, the scrollbar doesn’t stayed attached to the right side as expected.

This is the code:

from tkinter import *


class AutoScrollbar(Scrollbar):
    # a scrollbar that hides itself if it's not needed.  only
    # works if you use the pack geometry manager.
    def set(self, lo, hi):
        if float(lo) <= 0.0 and float(hi) >= 1.0:
            self.pack_forget()
        else:
            if self.cget("orient") == HORIZONTAL:
                self.pack(fill=X)
            else:
                self.pack(fill=Y)
        Scrollbar.set(self, lo, hi)

    def grid(self, **kw):
        raise (TclError, "cannot use grid with this widget")

    def place(self, **kw):
        raise (TclError, "cannot use place with this widget")


class Window1(Tk):
    def __init__(self):
        super().__init__()

        self.list_frame = Frame(self)
        self.list_frame.pack(fill=BOTH, expand=1)

        self.my_scrollbar = AutoScrollbar(self.list_frame, orient=VERTICAL)

        self.box1 = Listbox(self.list_frame, bg='black', fg='white',
                            width=60,
                            selectforeground='black',
                            yscrollcommand=self.my_scrollbar.set,
                            selectmode=EXTENDED)

        self.my_scrollbar.config(command=self.box1.yview)
        self.my_scrollbar.pack(side=RIGHT, fill=Y, pady=20)

        self.box1.pack(pady=20, fill=BOTH, expand=1)

        for num in range(15):
            self.box1.insert(END, num)


if __name__ == '__main__':
    w = Window1()
    w.mainloop()

This is the first view when I run the code:

enter image description here

When I expand the window the scrollbar disappears properly: enter image description here

But when I minimize the window, the scrollbar appears back but in an incorrect place and a strange shape: enter image description here

Advertisement

Answer

It is because you didn’t specify side option of pack() inside AutoScrollbar.set(), so it is TOP by default. Also you forgot to specify side in self.box1.pack(...).

Below is the modified code to fix the issues:

from tkinter import *


class AutoScrollbar(Scrollbar):
    # a scrollbar that hides itself if it's not needed.  only
    # works if you use the pack geometry manager.
    def set(self, lo, hi):
        if float(lo) <= 0.0 and float(hi) >= 1.0:
            self.pack_forget()
        else:
            if self.cget("orient") == HORIZONTAL:
                self.pack(fill=X, side=BOTTOM) # added side option
            else:
                self.pack(fill=Y, side=RIGHT)  # added side option
        super().set(lo, hi)

    def grid(self, **kw):
        raise (TclError, "cannot use grid with this widget")

    def place(self, **kw):
        raise (TclError, "cannot use place with this widget")


class Window1(Tk):
    def __init__(self):
        super().__init__()

        self.list_frame = Frame(self, pady=20) # added pady=20
        self.list_frame.pack(fill=BOTH, expand=1)

        self.my_scrollbar = AutoScrollbar(self.list_frame, orient=VERTICAL)

        self.box1 = Listbox(self.list_frame, bg='black', fg='white',
                            width=60,
                            selectforeground='black',
                            yscrollcommand=self.my_scrollbar.set,
                            selectmode=EXTENDED)

        self.my_scrollbar.config(command=self.box1.yview)
        self.my_scrollbar.pack(side=RIGHT, fill=Y) # removed pady=20

        self.box1.pack(fill=BOTH, expand=1, side=LEFT) # added side=LEFT and removed pady=20

        for num in range(15):
            self.box1.insert(END, num)


if __name__ == '__main__':
    w = Window1()
    w.mainloop()
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement