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:
JavaScript
x
51
51
1
from tkinter import *
2
3
4
class AutoScrollbar(Scrollbar):
5
# a scrollbar that hides itself if it's not needed. only
6
# works if you use the pack geometry manager.
7
def set(self, lo, hi):
8
if float(lo) <= 0.0 and float(hi) >= 1.0:
9
self.pack_forget()
10
else:
11
if self.cget("orient") == HORIZONTAL:
12
self.pack(fill=X)
13
else:
14
self.pack(fill=Y)
15
Scrollbar.set(self, lo, hi)
16
17
def grid(self, **kw):
18
raise (TclError, "cannot use grid with this widget")
19
20
def place(self, **kw):
21
raise (TclError, "cannot use place with this widget")
22
23
24
class Window1(Tk):
25
def __init__(self):
26
super().__init__()
27
28
self.list_frame = Frame(self)
29
self.list_frame.pack(fill=BOTH, expand=1)
30
31
self.my_scrollbar = AutoScrollbar(self.list_frame, orient=VERTICAL)
32
33
self.box1 = Listbox(self.list_frame, bg='black', fg='white',
34
width=60,
35
selectforeground='black',
36
yscrollcommand=self.my_scrollbar.set,
37
selectmode=EXTENDED)
38
39
self.my_scrollbar.config(command=self.box1.yview)
40
self.my_scrollbar.pack(side=RIGHT, fill=Y, pady=20)
41
42
self.box1.pack(pady=20, fill=BOTH, expand=1)
43
44
for num in range(15):
45
self.box1.insert(END, num)
46
47
48
if __name__ == '__main__':
49
w = Window1()
50
w.mainloop()
51
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:
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:
JavaScript
1
51
51
1
from tkinter import *
2
3
4
class AutoScrollbar(Scrollbar):
5
# a scrollbar that hides itself if it's not needed. only
6
# works if you use the pack geometry manager.
7
def set(self, lo, hi):
8
if float(lo) <= 0.0 and float(hi) >= 1.0:
9
self.pack_forget()
10
else:
11
if self.cget("orient") == HORIZONTAL:
12
self.pack(fill=X, side=BOTTOM) # added side option
13
else:
14
self.pack(fill=Y, side=RIGHT) # added side option
15
super().set(lo, hi)
16
17
def grid(self, **kw):
18
raise (TclError, "cannot use grid with this widget")
19
20
def place(self, **kw):
21
raise (TclError, "cannot use place with this widget")
22
23
24
class Window1(Tk):
25
def __init__(self):
26
super().__init__()
27
28
self.list_frame = Frame(self, pady=20) # added pady=20
29
self.list_frame.pack(fill=BOTH, expand=1)
30
31
self.my_scrollbar = AutoScrollbar(self.list_frame, orient=VERTICAL)
32
33
self.box1 = Listbox(self.list_frame, bg='black', fg='white',
34
width=60,
35
selectforeground='black',
36
yscrollcommand=self.my_scrollbar.set,
37
selectmode=EXTENDED)
38
39
self.my_scrollbar.config(command=self.box1.yview)
40
self.my_scrollbar.pack(side=RIGHT, fill=Y) # removed pady=20
41
42
self.box1.pack(fill=BOTH, expand=1, side=LEFT) # added side=LEFT and removed pady=20
43
44
for num in range(15):
45
self.box1.insert(END, num)
46
47
48
if __name__ == '__main__':
49
w = Window1()
50
w.mainloop()
51