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

PySimpleGUI列表框触发IndexError:列表索引越界问题求助

解决索引越界错误与列表框逻辑问题

问题分析

你的IndexError根源很明确:当点击Process按钮时,代码直接尝试获取列表框的第一个选中项values['-LISTBOX-'][0],但此时用户很可能还没有在列表框中选择任何选项,导致values['-LISTBOX-']是空列表,访问索引0自然会触发越界错误。

另外关于你提到的列表框显示为空的问题,看代码里listbox_values = list(fig_dict)是正确的,fig_dict有三个键值对,理论上列表框应该显示这三个选项。如果实际运行时为空,建议你在定义listbox_values后加一句print(listbox_values)确认值是否正确生成,大概率是逻辑顺序的问题——你现在的流程是点击Process就强制绘制图表,但用户还没来得及选列表项。

修复方案

我们需要调整逻辑:

  1. 先完成文件上传与处理,之后让用户主动选择列表框中的图表选项来触发绘制,而不是点击Process就直接绘制。
  2. 在任何访问列表框选中项的代码前,先判断是否有选项被选中,避免空列表索引错误。

修改后的完整代码如下:

import PySimpleGUI as sg
import time
import os
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.ticker import NullFormatter
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

sg.theme('Dark')

def PyplotSimple():
    t = np.arange(0., 5., 0.2)
    plt.plot(t, t, 'r--', t, t ** 2, 'bs', t, t ** 3, 'g^')
    fig = plt.gcf()
    return fig

def PyplotSimple2():
    t = np.arange(0., 5., 0.2)
    plt.plot(t, t, 'r--', t, t ** 2, 'b--', t, t ** 3, 'b--')
    fig = plt.gcf()
    return fig

def draw_plot():
    plt.plot([0.1, 0.2, 0.5, 0.7])
    fig = plt.gcf()
    return fig

def draw_figure(canvas, figure):
    figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
    figure_canvas_agg.draw()
    figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
    return figure_canvas_agg

def delete_figure_agg(figure_agg):
    figure_agg.get_tk_widget().forget()
    plt.close('all')

fig_dict = {'One Digit':PyplotSimple, 'Second Digit':PyplotSimple2,'First and Second Digit':draw_plot}
listbox_values = list(fig_dict)
# 确认列表框值是否正确生成
print(listbox_values)

col_listbox = [[sg.Listbox(values=listbox_values, enable_events=True, size=(40, len(listbox_values)), key='-LISTBOX-')],
               [sg.Text()]]

layout= [
    [sg.Text('my new GUI', size=(40,1),justification='c', font=("Arial 10"))],
    [sg.Text('Browse to file:'), sg.Input(size=(40,1), key='input'),sg.FileBrowse(key='filebrowse')],
    [sg.Button('Process' ,bind_return_key=True)],
    [sg.Col(col_listbox)],
    [sg.Canvas(size=(100, 100), background_color='white', key= 'CANVAS')],
    [sg.Exit()]
]

window = sg.Window('MY GUI', layout, grab_anywhere=False, finalize=True)

figure_agg = None
# 标记文件是否处理完成
file_processed = False

# The GUI Event Loop
while True:
    event, values = window.read()
    #print(event, values) # 调试时打开
    if event in (sg.WIN_CLOSED, 'Exit'):
        break
    if event == 'Process':
        inputfile = values['filebrowse']
        # 这里替换成你的文件处理逻辑
        if not inputfile:
            sg.popup('请先选择文件!', button_color=('#ffffff','#ff0000'))
            continue
        # 模拟文件处理
        time.sleep(1)
        sg.popup('Complete - view graphs',button_color=('#ffffff','#797979'))
        file_processed = True
    if event == '-LISTBOX-' and file_processed:
        # 当列表框被点击且文件已处理时,绘制图表
        if not values['-LISTBOX-']:
            continue
        choice = values['-LISTBOX-'][0]
        func = fig_dict[choice]
        fig = func()
        if figure_agg:
            delete_figure_agg(figure_agg)
        figure_agg = draw_figure(window['CANVAS'].TKCanvas, fig)
    elif event == '-LISTBOX-' and not file_processed:
        sg.popup('请先上传并处理文件!', button_color=('#ffffff','#ff0000'))

window.close()

关键修改点

  • 添加了file_processed变量,标记文件是否完成处理,避免用户未处理文件就点击列表框绘制图表。
  • 将图表绘制的逻辑从Process按钮事件移到了列表框的-LISTBOX-事件中,这样只有用户选择了列表项才会触发绘制,从根源避免了空列表索引错误。
  • 在访问列表框选中项前增加了非空判断,双重保险防止越界。
  • 增加了未选择文件时的提示,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 18:02:45