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:
When I expand the window the scrollbar disappears properly:
But when I minimize the window, the scrollbar appears back but in an incorrect place and a strange shape:
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.