如何在PySimpleGUI的sg.Table中动态隐藏寄存器关联字段行?
实现PySimpleGUI表格分组行动态显示/隐藏
核心思路
PySimpleGUI的Table组件没有原生折叠/展开行的功能,我们可以通过维护数据行的显示状态,配合UI控件动态更新表格数据来实现需求。
具体实现步骤
1. 预处理数据结构
给寄存器和字段标记层级关系,同时记录寄存器对应的字段行范围:
# 从JSON提取后整理的数据示例 data = [ {"type": "register", "name": "REG_A", "addr": 0x00, "level": 0, "fields_start": 1, "fields_end": 3}, {"type": "field", "name": "FIELD_A1", "bit": "0-3", "level": 1, "parent": "REG_A"}, {"type": "field", "name": "FIELD_A2", "bit": "4-7", "level": 1, "parent": "REG_A"}, {"type": "field", "name": "FIELD_A3", "bit": "8-15", "level": 1, "parent": "REG_A"}, {"type": "register", "name": "REG_B", "addr": 0x04, "level": 0, "fields_start": 4, "fields_end": 6}, {"type": "field", "name": "FIELD_B1", "bit": "0-7", "level": 1, "parent": "REG_B"}, {"type": "field", "name": "FIELD_B2", "bit": "8-15", "level": 1, "parent": "REG_B"}, {"type": "register", "name": "REG_C", "addr": 0x08, "level": 0, "fields_start": 7, "fields_end": 8}, {"type": "field", "name": "FIELD_C1", "bit": "0-15", "level": 1, "parent": "REG_C"}, ]
2. 维护显示状态变量
- 用字典记录单个寄存器的展开状态:
register_expanded = {"REG_A": False, "REG_B": False, "REG_C": False} - 全局展开/折叠开关状态:
global_expanded = False
3. 构建UI布局
在表格首列添加+/-切换按钮,同时加入全局控制复选框:
import PySimpleGUI as sg # 表格列标题 headings = ["", "类型", "名称", "地址/位段"] # 根据状态生成要显示的表格数据 def get_display_data(): display_rows = [] for row in data: if row["level"] == 0: # 寄存器行显示+/-,根据展开状态切换 toggle_char = "-" if register_expanded[row["name"]] or global_expanded else "+" display_rows.append([toggle_char, "寄存器", row["name"], hex(row["addr"])]) # 若展开则追加对应字段行 if register_expanded[row["name"]] or global_expanded: for field_row in data[row["fields_start"]:row["fields_end"]+1]: display_rows.append(["", "字段", field_row["name"], field_row["bit"]]) return display_rows # 组装布局 layout = [ [sg.Checkbox("全局展开所有字段", key="-GLOBAL_TOGGLE-", enable_events=True)], [sg.Table(values=get_display_data(), headings=headings, key="-TABLE-", auto_size_columns=True, enable_events=True)], ] window = sg.Window("寄存器字段表格", layout)
4. 处理事件逻辑
监听表格点击和全局开关事件,更新状态后刷新表格:
while True: event, values = window.read() if event == sg.WIN_CLOSED: break # 全局开关触发时更新状态并刷新表格 if event == "-GLOBAL_TOGGLE-": global_expanded = values["-GLOBAL_TOGGLE-"] window["-TABLE-"].update(values=get_display_data()) # 表格行点击事件,处理单个寄存器的展开/折叠 if event == "-TABLE-": selected_rows = values["-TABLE-"] if selected_rows: display_idx = selected_rows[0] display_data = get_display_data() # 判断是否点击了寄存器行的切换按钮 if display_data[display_idx][0] in ["+", "-"]: reg_name = display_data[display_idx][2] register_expanded[reg_name] = not register_expanded[reg_name] window["-TABLE-"].update(values=get_display_data()) window.close()
关键说明
- 必须开启表格的
enable_events=True才能捕获行点击事件 get_display_data()是核心函数,根据当前状态动态生成显示行- 字段行通过首列留空实现视觉缩进,区分层级
内容的提问来源于stack exchange,提问作者eliljey
相关产品推荐
相关产品推荐

