如何在PySimpleGUI中实现两列复选框以操作Pandas DataFrame的In_Possession列值
实现PySimpleGUI复选框控制Pandas DataFrame数据
你的思路方向是对的,但Tree控件确实不太适合这种互斥复选框的交互场景,换成Table控件会更直观且容易实现界面与数据的双向绑定。我帮你调整了代码,实现通过TRUE/FALSE两列的复选框来修改DataFrame的In_Possession值,同时保证两列复选框互斥(选了TRUE就不能选FALSE,反之亦然)。
修改后的完整代码
import PySimpleGUI as sg import pandas as pd from io import BytesIO from PIL import Image, ImageDraw def get_checkbox_icon(is_checked, is_disabled=False): """生成复选框图标:支持未选中、选中、禁用(灰色选中)三种状态""" box_size = (32, 32) background = (255, 255, 255, 0) rectangle = (3, 3, 29, 29) check_line = ((9, 17), (15, 23), (23, 9)) im = Image.new('RGBA', box_size, background) draw = ImageDraw.Draw(im, 'RGBA') # 绘制复选框边框,禁用状态用灰色边框 draw.rectangle(rectangle, outline='black' if not is_disabled else 'grey', width=3) if is_checked: # 绘制勾选标记,禁用状态用灰色标记 draw.line(check_line, fill='black' if not is_disabled else 'grey', width=3, joint='curve') with BytesIO() as output: im.save(output, format="PNG") return output.getvalue() # 预生成三种状态的图标 icon_unchecked = get_checkbox_icon(False) icon_checked = get_checkbox_icon(True) icon_disabled_checked = get_checkbox_icon(True, is_disabled=True) # 初始化DataFrame genshin_characters = { 'CHARACTER_NAME': ['Amber','Jean','Lisa','HuTao'], 'In_Possession': [True, False, True, False] } df = pd.DataFrame(genshin_characters) # 把DataFrame数据转换成Table需要的格式:每行包含角色名、TRUE列图标、FALSE列图标 def update_table_data(): table_data = [] for _, row in df.iterrows(): if row['In_Possession']: # 拥有角色:TRUE列选中,FALSE列禁用 table_data.append([row['CHARACTER_NAME'], icon_checked, icon_disabled_checked]) else: # 未拥有角色:FALSE列选中,TRUE列禁用 table_data.append([row['CHARACTER_NAME'], icon_disabled_checked, icon_checked]) return table_data # 设置PySimpleGUI主题和字体 sg.theme('LightPurple') sg.set_options(font=('Helvetica', 16)) # 构建布局:使用Table控件替代Tree,更适合行列数据交互 layout = [ [sg.Table( values=update_table_data(), headings=['CHARACTER_NAME', 'TRUE', 'FALSE'], auto_size_columns=False, col_widths=[20, 6, 6], # 手动设置列宽,适配复选框图标大小 num_rows=10, key='-TABLE-', row_height=48, enable_events=True, # 开启点击事件监听 select_mode=sg.TABLE_SELECT_MODE_BROWSE )], [sg.Button('Submit'), sg.Button('Quit')] ] window = sg.Window('Character Collection', layout, finalize=True) table = window['-TABLE-'] while True: event, values = window.read() if event in (sg.WINDOW_CLOSED, 'Quit'): break elif event == '-TABLE-': # 获取用户点击的行和列索引 selected = values['-TABLE-'] if not selected: continue row_idx = selected[0] col_idx = table.CurrentColumn # 根据点击的列更新DataFrame数据 if col_idx == 1: # 点击了TRUE列 df.at[row_idx, 'In_Possession'] = True elif col_idx == 2: # 点击了FALSE列 df.at[row_idx, 'In_Possession'] = False # 同步更新Table显示 table.update(values=update_table_data()) elif event == 'Submit': # 提交时打印更新后的DataFrame,方便验证数据正确性 print("更新后的角色拥有状态:") print(df) sg.popup("数据已更新!可查看控制台输出详情") window.close()
关键功能说明
互斥复选框逻辑:
- 点击TRUE列时,将对应行的
In_Possession设为True,同时把FALSE列的复选框设为灰色禁用状态(避免重复点击) - 点击FALSE列时则相反,确保同一行只能有一个选项生效
- 点击TRUE列时,将对应行的
DataFrame双向同步:
- 每次点击复选框都会直接修改DataFrame的
In_Possession值,保证界面显示与底层数据完全一致 update_table_data()函数负责将DataFrame数据转换成Table需要的图标格式,每次修改后重新渲染界面
- 每次点击复选框都会直接修改DataFrame的
用户体验优化:
- 手动设置列宽,让复选框显示更协调
- 禁用未选中的列,减少无效操作
- Submit按钮点击后弹出提示,并在控制台打印完整数据,方便验证修改结果
内容的提问来源于stack exchange,提问作者Ricky Shie
相关产品推荐
相关产品推荐

