Tkinter实现带自动隐藏滚动条的Listbox问题求助
Listbox自动隐藏滚动条位置异常问题
我想要创建一个带有自动隐藏滚动条的Listbox,找到一个类示例测试,但滚动条无法始终附着在右侧;窗口缩小时,滚动条重新出现但位置错误、形状怪异。
测试代码
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()
问题现象
- 首次运行视图:

- 窗口放大时滚动条正常隐藏:

- 窗口缩小时滚动条异常:

问题原因
原代码中,AutoScrollbar在重新显示时仅调用pack(fill=Y),没有保留初始的side=RIGHT和pady=20参数,导致滚动条默认从顶部布局,且无上下边距,出现位置偏移和形状怪异的问题。
修复方案
修改AutoScrollbar类,保存初始的pack配置参数,重新显示时复用这些参数:
from tkinter import * from tkinter import TclError class AutoScrollbar(Scrollbar): # 自动隐藏的滚动条,仅支持pack布局 def __init__(self, master=None, **kwargs): super().__init__(master, **kwargs) self.pack_config = {} # 保存pack的布局参数 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, **self.pack_config) else: self.pack(fill=Y, **self.pack_config) super().set(lo, hi) def pack(self, **kwargs): self.pack_config = kwargs # 记录当前pack的配置 super().pack(**kwargs) 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()
修复说明
- 新增
pack_config属性,用于保存滚动条第一次pack时的布局参数(如side=RIGHT、pady=20) - 重写
pack方法,每次调用pack时更新保存的配置参数 - 在
set方法中重新显示滚动条时,传入保存的配置参数,确保布局和初始状态一致 - 修正了
TclError的抛出方式,符合Python语法规范
内容的提问来源于stack exchange,提问作者David 04
相关产品推荐
相关产品推荐

