【问题标题】:Stop Text widget from scrolling when content is changed内容更改时停止滚动文本小部件
【发布时间】:2011-01-16 06:37:35
【问题描述】:

我有一个带有滚动条的文本小部件,看起来像这样:

self.myWidget = Text(root) 
self.myWidget.configure(state=DISABLED)
self.myWidget.pack()

self.myWidgetScrollbar = Scrollbar(root, command=self.myWidget.yview)
self.myWidget.configure(yscrollcommand=self.myWidgetScrollbar.set)
self.myWidgetScrollbar.pack(side=LEFT,fill=Y)

文本小部件每秒更新 4 次:

self.myWidget.configure(state=NORMAL)
self.myWidget.delete(1.0, END) 
self.myWidget.insert(END, "\n".join(self.listWithStuff))  
self.myWidget.configure(state=DISABLED)

问题在于,当我尝试滚动时,它会不断将我滚动回顶部(可能每秒 4 次)。我认为这是因为所有内容都被删除了。

如何防止它自动滚动,或者当内容发生变化时可能会“向后”滚动?

【问题讨论】:

    标签: python scrollbar tkinter


    【解决方案1】:

    您可以保护位置并在更新后将其重新设置,就像下面的 Tcl 代码一样:

    proc update_view {w s data} {
      # store position
      set pos [$s get]
      $w configure -state normal -yscrollcommand {}
      $w delete 1.0 end
      $w insert end $data
      $w configure -state disabled -yscrollcommand [list $s set]
      $s get
      $s set {*}$pos
    }
    

    Tkinter 代码看起来很相似,类似于:

    def update_view(self, data):
        pos = self.myWidgetScrollbar.get()
        self.myWidget.configure(yscrollcommand=None, state=NORMAL)
        self.myWidget.delete(1.0, END)
        self.myWidget.insert(END, data)
        self.myWidget.configure(yscrollcommand=self.myWidgetScrollbar.set, state=DISABLED)
        self.myWidgetScrollbar.get()
        self.myWidgetScrollbar.set(pos)
    

    不确定为什么需要中间的 get(),也许是为了强制进行一些查找,但它确实有效。

    【讨论】:

    • 我很确定这会奏效,但遗憾的是,它没有。每次更新后它会一直向上滚动到顶部。另外,get 方法会随机引发异常,例如“ValueError: invalid literal for float(): None0.0”,这是怎么回事?
    • 通过玩弄你的解决方案,我让它工作了,虽然 set-method 似乎不太好用,但当我使用列表框中的 yview_moveto 时,它工作得很好。这是(基本上)代码:codepos = scrollbar.get()#remove old content#add new contentlistWidget.yview_moveto(pos[0])哦,异常是由线程问题引起的。 Tkinter 不是线程安全的,必须在单个线程中维护,我通过使用 widget.after 而不是使用 sleep 并将函数放在它自己的线程中解决了我的问题。
    【解决方案2】:

    您可以在每次更新后使用 Text 小部件的 yview 方法跳转到小部件的底部。此外,为了防止用户在尝试滚动时跳跃而让用户感到沮丧,您可以做一个简单的检查以确保滚动条已经在底部(a.k.a '不滚动)。

    if self.myWidgetScrollbar.get() == 1.0:
        self.myWidget.yview(END)
    

    【讨论】:

    • 我建议改用self.myWidgetScrollbar.get()[1]
    猜你喜欢
    • 2017-08-14
    • 2011-11-11
    • 2021-06-24
    • 1970-01-01
    • 1970-01-01
    • 2020-05-02
    • 2011-12-29
    • 1970-01-01
    • 2021-10-20
    相关资源
    最近更新 更多