自定义 Tk Scrollable Frame 在窗口未满时滚动

问题描述 投票:0回答:1

我一直在尝试使用此处的许多答案和分散的指南使用 Tkinter / ttk 创建一个可滚动框架。框架用于保存一个可以添加和删除行的表。我遇到的一个在其他地方找不到的问题是,如果框架内有空间容纳更多内容,我可以将表格的内容滚动到框架的底部。当框架已满时,它的行为符合预期。

我目前无法转换为 gif,因此我添加了一些屏幕截图来尝试说明。

这是我的可滚动框架类,从网络上的示例来看,它非常标准;

class ScrollableFrame(ttk.Frame):

    def __init__(self, parent):

        super().__init__(parent)
        
        self.canvas = tk.Canvas(self)
        self.scrollbar = ttk.Scrollbar(self, orient="vertical", command=self.canvas.yview)
        self.scrollableFrame = ttk.Frame(self.canvas)
        self.canvas.configure(yscrollcommand=self.scrollbar.set)
        
        self.scrollableFrame.bind("<Configure>", lambda e: self.canvas.configure(scrollregion=self.canvas.bbox("all")))
        self.bind("<Enter>", self.bind_to_mousewheel)
        self.bind("<Leave>", self.unbind_from_mousewheel)
        
        self.scrollbar.pack(side='right', fill='y')
        self.canvas.pack(side='top', expand=0, fill='x')
        self.canvas.create_window((0, 0), window=self.scrollableFrame)
        
    def bind_to_mousewheel(self, event):
        self.canvas.bind_all("<MouseWheel>", self.on_mousewheel)
        
    def unbind_from_mousewheel(self, event):
        self.canvas.unbind_all("<MouseWheel>")

    def on_mousewheel(self, event):
        self.canvas.yview_scroll(int(-1*(event.delta/120)), "units")

表格行由父 GUI 添加到

ScrollableFrame.scrollableFrame
小部件,我认为这是触发绑定到
<Configure>
ScrollableFrame.canvas
所必需的。

有人有什么建议吗?

无需滚动,因为框架未满 No scroll required as frame not full

表格仍然滚动 Table still scrolls

滚动停止,行小部件位于框架底部 Scroll stops with row widgets at bottom of frame

python user-interface tkinter scroll
1个回答
0
投票

感谢@acw1668的提示,我找到了答案;

我调整了

<Configure>
命令来检查
scrollregion
的大小并将其与父
ScrollableFrame
类窗口进行比较。如果它更小,我将滚动区域更改为
ScrollableFrame
的大小。

这是我对班级所做的调整,包括将窗口锚点更改为位于框架的左上角;

class ScrollableFrame(ttk.Frame):
    """
    """
    def __init__(self, parent):
        """
        """
        ...
        self.scrollableFrame.bind("<Configure>", self.update_scroll_region)
        ...
        self.canvas.create_window((0, 0), window=self.scrollableFrame, anchor='nw')

    def update_scroll_region(self, event):
        bbox = self.canvas.bbox('all')  
        sfHeight = self.winfo_height()
        if (bbox[3] - bbox[1]) < sfHeight:
            newBbox = (bbox[0], 0, bbox[2], sfHeight)
            self.canvas.configure(scrollregion=newBbox)
        else:
            self.canvas.configure(scrollregion=self.canvas.bbox("all"))
© www.soinside.com 2019 - 2024. All rights reserved.