更改内容时停止文本小部件滚动

3 投票
2 回答
4423 浏览
提问于 2025-04-16 10:02

我有一个带滚动条的文本小部件,样子大概是这样的:

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次)。我猜这是因为所有内容都被移除了。

我该怎么做才能防止它自动滚动,或者在内容改变时能“回滚”一下呢?

2 个回答

1

你可以在每次更新后,使用文本框的yview方法直接跳到底部。为了避免在用户尝试滚动时让他们感到烦恼,你可以简单检查一下,确保滚动条已经在底部(也就是说,用户并没有在滚动)。

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

你可以先保存当前位置,然后在更新后再把它设置回去,就像下面这个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()为什么需要,可能是为了强制进行某种查找,但这样做是有效的。

撰写回答