如何在Tkinter中创建带滚动条的LabelFrame?

4 投票
1 回答
11787 浏览
提问于 2025-04-16 23:54

我正在用Python和Tkinter创建一个程序的图形界面,但遇到了一些问题。

我有三个从LabelFrame派生的对象,这些对象又是在一个从Frame派生的对象里面。其中一个LabelFrame的子类包含了两列对应的Label和Entry对象。

freq_frame example

问题是,Label和Entry的配对数量不固定,有时候会超过屏幕能显示的范围。我需要为这个LabelFrame添加一个滚动条,这样所有内容才能在屏幕上显示。我尝试了几种方法来创建一个滚动条对象,但都没有成功。我该如何将滚动条绑定到这个框架上呢?

另外,当调用load_message()方法时,我需要能够刷新或重新加载这个LabelFrame,但它只是把新的配对显示在旧的配对上面(所以当新的配对数量少时,旧的配对仍然在底部可见)。我尝试使用grid_forget(),但要么没有任何变化,要么整个框架都不显示。我该如何清除这个显示,然后再重新显示呢?

这是这个类的代码:

class freq_frame(LabelFrame):
    def __init__(self, master = None, text = 'Substitutions'):
        LabelFrame.__init__(self, master, text = text)
        self.grid()
    def load_message(self):
        self.frequency = get_freq(message)
        self.create_widgets()
    def create_widgets(self):
        self.label_list = [Label(self, text = get_label(char, self.frequency[char]), justify = LEFT) for char in self.frequency.keys()]
        self.entry_list = [Entry(self, width = 1) for char in self.frequency.keys()]
        for n in range(len(self.label_list)):
            self.label_list[n].grid(column = 0, row = n)
        for n in range(len(self.entry_list)):
            self.entry_list[n].grid(column = 1, row = n)

如果有人能帮我解决这两个问题,我将非常感激。

另外,这个问题看起来可能有点简单,但我不知道该补充什么。如果需要更多信息,请随时问我(但请具体一点)。

谢谢!

1 个回答

4

Labelframe(标签框)不支持滚动。所以,简单来说,你不能让它滚动。这听起来很明显,但如果一个组件的说明书上没有提到它支持滚动,那它就真的不支持滚动。

不过,有个简单的解决办法。首先,在labelframe里面加一个画布(canvas),并把它设置成填满labelframe。然后给这个画布加上滚动条,并把滚动条也放到labelframe里。接着在画布里再嵌套一个框架(frame),把你的组件放到这个内部框架里。最后,在你添加完所有的标签和输入框后,调整画布的滚动区域,让它和内部框架的大小一致。

听起来可能有点复杂,但其实很简单。

至于在调用load_message时重新创建组件,调用grid_forget只是把它们从视图中移除,并没有真正销毁这些组件。随着时间的推移,你可能会有成百上千个看不见的组件,这肯定不是你想要的。

所以,你首先要销毁所有现有的组件。如果它们都在同一个父级下,这样做很简单,因为你可以向父级请求它所有孩子的列表。然后遍历这个列表,删除每一个孩子,再添加新的孩子。一个更简单的办法是直接销毁并重新创建那个包含标签和输入框的内部框架。当你删除一个组件时,所有子组件会自动被销毁。所以,删除那个内部框架,创建一个新的,再把你的标签和输入框加进去。

撰写回答