如何使用python tkinter在列表框中添加自动隐藏滚动条

b5buobof  于 2023-03-13  发布在  Python
关注(0)|答案(1)|浏览(208)

我怎样用python tkinter在列表框中添加自动隐藏滚动条?例如,当列表框的大小小于或等于框架的大小时隐藏滚动条,否则重新出现.
我写了一个代码,为我创建了一个带有滚动框的列表框。它是完全工作的,现在我想添加隐藏滚动框的能力。

import tkinter
from tkinter import ttk

class ScrollingListbox(ttk.Frame):
    def __init__(self, master, width=80, selectmode="multiple", borderwidth=0, highlightthickness=0):
        ttk.Frame.__init__(self, master)

        self._scrollbar_vertical = ttk.Scrollbar(self)
        self._scrollbar_vertical.pack(side=tkinter.RIGHT, fill=tkinter.Y)

        self._scrollbar_horizontal = ttk.Scrollbar(self, orient="horizontal")
        self._scrollbar_horizontal.pack(side=tkinter.BOTTOM, fill=tkinter.X)

        self._listbox_playlist_tracks = tkinter.Listbox(self, width=width, selectmode=selectmode,
                                                        yscrollcommand=self._scrollbar_vertical.set,
                                                        xscrollcommand=self._scrollbar_horizontal.set,
                                                        borderwidth=borderwidth, highlightthickness=highlightthickness)
        self._listbox_playlist_tracks.pack(expand=1, fill=tkinter.BOTH, padx=5, pady=5)
        self._scrollbar_vertical.config(command=self._listbox_playlist_tracks.yview)
        self._scrollbar_horizontal.config(command=self._listbox_playlist_tracks.xview)

    def insert(self, index=tkinter.END, value=0):
        self._listbox_playlist_tracks.insert(index, value)

    def delete(self, first=0, last=tkinter.END):
        self._listbox_playlist_tracks.delete(first, last)

    def foo(self):
        new_height = self.winfo_height()
        min_height = self._listbox_playlist_tracks.winfo_reqheight()
        print(f'f={new_height}, l={min_height}')

if __name__ == '__main__':
    root = tkinter.Tk()
    root.geometry('700x500')
    _listbox_playlist_tracks = ScrollingListbox(root)
    _listbox_playlist_tracks.pack(expand=1, fill=tkinter.BOTH, padx=5, pady=5)

    for i in range(500):
        _listbox_playlist_tracks.insert(tkinter.END, i)
    _listbox_playlist_tracks.foo()

我尝试用类似于this implementation的方法来实现它,但是winfo_reqwidth()方法总是产生相同的值。也许还有其他一些方法可以获得列表框的尺寸,并将其与父框架的尺寸进行比较。
我在这里找到了另一个canvas的例子:https://www.geeksforgeeks.org/autohiding-scrollbars-using-python-tkinter/

ohtdti5x

ohtdti5x1#

其基本思路如下:
只有在小部件改变大小或更改列表框的内容时,才需要隐藏或显示滚动条。在这种情况下,您可以查询小部件的xviewyview,以查看可滚动区域是否大于列表框的可见部分。如果所有内容都适合,调用xviewyview函数的结果将是元组(0.0, 1.0)。当某些内容滚动到可见区域之外时,这些数字将发生变化。
因此,首先创建一个函数来执行计算,然后隐藏或显示滚动条。如果您使用grid而不是pack,这是最简单的,因为grid可以记住它的配置。然而,您可以使用pack,只需稍微多做一些工作。
对于垂直滚动条,它可能如下所示:

def _manage_scrollbar(self, event=None):
    yview = self._listbox_playlist_tracks.yview()
    if yview == (0.0, 1.0):
        self._scrollbar_vertical.pack_forget()
    else:
        self._scrollbar_vertical.pack(before=self._scrollbar_horizontal,
                                      side=tkinter.RIGHT, fill=tkinter.Y)

然后,当您修改列表框的内容时,可以调用此函数:

for i in range(50):
    _listbox_playlist_tracks.insert(tkinter.END, i)
self._manage_scrollbar()

最后,将此函数绑定到列表框的<Configure>事件,以便当小部件的大小发生变化时,调用此函数:

class ScrollingListbox(ttk.Frame):
    def __init__(self, master, width=80, selectmode="multiple", borderwidth=0, highlightthickness=0):       
        ...
        self._listbox_playlist_tracks.bind("<Configure>", self._manage_scrollbar)

相关问题