将 Tkinter 滚动条跳转到某个小部件

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

我在我的 Tkinter GUI 中添加了一些滚动条功能,如下所示

self.canvas = tk.Canvas(self.baseframe)
self.scrollbar = tk.Scrollbar(self.baseframe, orient="vertical", command=self.canvas.yview)
self.scrollable = tk.Frame(self.canvas)
self.scrollable.bind("<Configure>", lambda e: self.canvas.configure(scrollregion=self.canvas.bbox("all")))
self.canvas.create_window((0, 0), window=self.scrollable, anchor="n")
self.canvas.configure(yscrollcommand=self.scrollbar.set)
self.canvas.bind_all("<MouseWheel>", self._mousescroll)

我已将

_mousecroll()
定义为

    def _mousescroll(self, event):
        """mouse wheel scroll callback"""
        # Divide the event.delta by some value to effect the scrolling speed
        self.canvas.yview_scroll(int(-1*(event.delta/120)), "units")

效果很好。

然后我向滚动区域添加一些

tkLabelFrame
小部件(它们本身包含显示内容的小部件 - 与这个问题无关)。整个滚动功能非常好用。

在我的 GUI 的其他部分,我希望用户能够通过单击按钮“跳转”到滚动区域中的特定点。实际上,滚动区域会自动滚动到这一点。这可能吗?我可以完全控制 GUI 代码,因此我可以将标签添加到 tkLabelFrames 列表中,将它们存储在某种列表/字典中,以便可以轻松查找它们......类似的东西?

注意:添加到滚动区域的

tkLabelFrames
数量是动态的,因此某种绝对的“跳转到这么多像素”可能不起作用。我希望可能有某种“滚动到带有此标签/属性等的小部件......”功能。任何帮助表示赞赏。谢谢。

python tkinter
3个回答
2
投票

我正在恢复这个,因为它是谷歌中的第一个结果,并不是每个人的小部件都具有相同的高度(根据当前接受的答案的解决方案的要求)。


使用一些 .winfo 函数,我们可以做一些快速数学运算来找到我们想要跳转到“self.scrollable”中的确切位置的小部件。

注意: 在调用跳转函数之前,您可能需要在 tkinter 实例上调用 .update(),否则 winfo 值可能不正确。


我们将使用以下内容:

  • .winfo_height() - 获取此小部件的高度(以像素为单位)。如果窗口不受几何管理器管理,将返回 1

  • .winfo_rooty() - 获取小部件上边缘相对于屏幕左上角的像素坐标。

  • .yview_moveto(fraction) - 将视图移动到位置。 0 为顶部,1 为底部


以下函数将跳转到给定的小部件,将其放置在可视区域(self.canvas)的顶部。

 def jump_to_widget_top(self, widget):
      if self.scrollable.winfo_height() > self.canvas.winfo_height():
           pos = widget.winfo_rooty() - self.scrollable.winfo_rooty()
           height = self.scrollable.winfo_height()
           self.canvas.yview_moveto(pos / height)

首先我们检查容器(self.scrollable)实际上是否大于查看区域。如果所有内容都已显示,则无需跳转。

我们找到所需小部件的绝对位置(相对于屏幕),然后减去容器顶部(self.scrollable)到屏幕顶部的距离。这为我们提供了相对于容器位置的小部件位置。

找到小部件的位置后,将其除以容器的高度(self.scrollable),我们就得到了小部件的小数位置,根据 .yview_moveto() 的要求。



1
投票

对于我的特定场景,可滚动区域内的小部件都具有相同的高度,因此我能够使用简单的分数滚动到正确的位置。

添加一个按钮,并回调这样的方法对我有用:

def scrollto(self, idx):
    # Where self.frames is the list of tkLabelFrame objects.
    fraction = float(idx/len(self.frames))

    # self.canvas is my scrollable canvas
    self.canvas.yview_moveto(fraction)

0
投票
只要小部件不发生变化,Elija B. 的

jump_to_widget_top
就可以很好地工作。这确实是滚动窗口的错误(因此,如果您使用滚动条,滚动条也无法正常工作)。我不得不打电话
self.canvas.configure(scrollregion=self.canvas.bbox('all'))
在计算
yview_moveto
比率之前。

© www.soinside.com 2019 - 2024. All rights reserved.