Home > database >  How to make a scrollable listbox? tkinter python
How to make a scrollable listbox? tkinter python

Time:12-21

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

CodePudding user response:

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()

CodePudding user response:

@David 04. Your code is working. You cannot used less than 15. Unless you set geometry or resizable. should solved your problem.

Change this:

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

to:

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

You will get scrollable resizing.

  • Related