You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何防止PySimpleGUI Listbox添加新数据时滚动条自动回顶

解决PySimpleGUI Listbox更新时滚动条跳回顶部的问题

你的问题根源在于每次调用window["-NUMBERS-"].update(list_of_numbers)时,Listbox会完全重新渲染整个列表,导致滚动条被强制重置到顶部。下面提供两种直接可行的解决方法:

方法一:仅追加新元素(推荐)

让后台线程只传递新增的单个元素,主窗口用append=True参数将元素添加到Listbox,避免重新渲染整个列表。

修改后的完整代码:

import queue
from threading import Thread
from time import sleep

import PySimpleGUI as sg

numbers_queue = queue.Queue()


def add_number_to_list(numbers_queue):
    for i in range(0, 20):
        sleep(0.5)
        # 只传递新增的单个数字,而非整个列表
        numbers_queue.put(i)


layout = [
    [sg.Text("Hello from PySimpleGUI")],
    [sg.Button("Start")],
    [sg.Listbox(values=[], enable_events=True, size=(40, 10), key="-NUMBERS-")]
]

window = sg.Window(title="Hello World", layout=layout, margins=(500, 500))

while True:
    event, values = window.read(timeout=100)

    if event == sg.WIN_CLOSED:
        break

    if event == "Start":
        numbers_thread = Thread(target=add_number_to_list, args=(numbers_queue,), daemon=True)
        numbers_thread.start()

    try:
        new_num = numbers_queue.get_nowait()
        # 使用append=True追加新元素,不触发滚动条重置
        window["-NUMBERS-"].update([new_num], append=True)
    except queue.Empty:
        pass

window.close()

方法二:记录并恢复滚动位置

如果业务场景要求必须全量更新列表(比如列表存在修改、删除操作),可以先获取当前滚动位置,更新后再恢复:

修改主循环中处理列表更新的部分:

try:
    list_of_numbers = numbers_queue.get_nowait()
    if list_of_numbers:
        # 获取当前滚动条位置
        listbox_widget = window["-NUMBERS-"].Widget
        scroll_pos = listbox_widget.yview()
        
        # 全量更新列表
        window["-NUMBERS-"].update(list_of_numbers)
        
        # 恢复之前的滚动位置
        listbox_widget.yview_moveto(scroll_pos[0])
except queue.Empty:
    pass

关键说明:

  • 方法一效率更高,适合仅新增元素的场景,从根源上避免滚动条跳动。
  • 方法二通过操作底层tkinter组件实现位置保存,适用于需要全量更新列表的复杂场景。

内容的提问来源于stack exchange,提问作者Andrew

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 19:06:25