如何基于PySimpleGUI筛选GUI输入行以生成有效XSLT文件
解决PySimpleGUI动态行的输出过滤问题
你需要过滤三类无效行,避免它们进入XSLT生成逻辑:隐藏行、未勾选「Pass as output」的行、输入为空的行。以下是两种可行方案,附可运行的实验代码。
方案一:直接过滤values字典(最简便)
PySimpleGUI的values会捕获所有控件值,不管控件是否可见,因此可以通过控件key的命名规律,遍历每一行的控件,逐一验证有效性:
实验代码
import PySimpleGUI as sg # 基础行布局 def create_row(index): return [ sg.Checkbox("Pass as output", key=f"-PASS_{index}-", default=True), sg.Input(key=f"-CSV_COL_{index}-", size=(20,1), placeholder="CSV表头"), sg.Input(key=f"-XML_TAG_{index}-", size=(20,1), placeholder="XML标签"), sg.Button("隐藏行", key=f"-HIDE_{index}-"), sg.Button("显示行", key=f"-SHOW_{index}-", visible=False) ] # 初始布局 layout = [ [sg.Button("添加映射行", key="-ADD_ROW-")], [sg.Column([create_row(0)], key="-ROWS_CONTAINER-")], [sg.Button("生成XSLT映射", key="-GENERATE-"), sg.Output(size=(60,10))] ] window = sg.Window("CSV到XML映射工具", layout) row_index = 1 while True: event, values = window.read() if event == sg.WIN_CLOSED: break # 动态添加行 if event == "-ADD_ROW-": window.extend_layout(window["-ROWS_CONTAINER-"], [create_row(row_index)]) row_index += 1 # 隐藏/显示行 if event.startswith("-HIDE_"): idx = int(event.split("_")[1]) # 隐藏该行所有控件 for key in [f"-PASS_{idx}-", f"-CSV_COL_{idx}-", f"-XML_TAG_{idx}-", f"-HIDE_{idx}-"]: window[key].update(visible=False) window[f"-SHOW_{idx}-"].update(visible=True) if event.startswith("-SHOW_"): idx = int(event.split("_")[1]) # 显示该行所有控件 for key in [f"-PASS_{idx}-", f"-CSV_COL_{idx}-", f"-XML_TAG_{idx}-", f"-HIDE_{idx}-"]: window[key].update(visible=True) window[f"-SHOW_{idx}-"].update(visible=False) # 生成映射并过滤无效行 if event == "-GENERATE-": valid_mappings = {} # 遍历所有行索引(从0到当前最大index-1) for idx in range(row_index): # 1. 检查是否勾选Pass if not values.get(f"-PASS_{idx}-", False): continue # 2. 检查控件是否可见 if not window[f"-CSV_COL_{idx}-"].visible: continue # 3. 检查输入是否非空 csv_col = values.get(f"-CSV_COL_{idx}-", "").strip() xml_tag = values.get(f"-XML_TAG_{idx}-", "").strip() if not csv_col or not xml_tag: continue # 加入有效映射 valid_mappings[csv_col] = xml_tag # 模拟生成XSLT逻辑(这里仅打印有效映射) print("===== 有效映射(用于生成XSLT) =====") if valid_mappings: for csv, xml in valid_mappings.items(): print(f"<xsl:value-of select='{csv}'/> -> <{xml}/>") else: print("无有效映射行") window.close()
方案二:用容器控件管理行(更清晰)
把每一行封装到sg.Frame中,通过容器的可见性和自定义属性标记有效性,过滤时直接检查容器状态:
核心修改点
- 把行布局放到
sg.Frame里,给Frame设置key:sg.Frame(f"行 {index}", create_row_inner(index), key=f"-ROW_FRAME_{index}-") - 隐藏/显示时直接操作Frame的可见性
- 过滤时遍历Frame控件,检查可见性、复选框状态和输入值
代码片段(仅展示差异部分)
# 修改create_row为返回Frame容器 def create_row(index): def create_row_inner(): return [ sg.Checkbox("Pass as output", key=f"-PASS_{index}-", default=True), sg.Input(key=f"-CSV_COL_{index}-", size=(20,1), placeholder="CSV表头"), sg.Input(key=f"-XML_TAG_{index}-", size=(20,1), placeholder="XML标签"), sg.Button("隐藏行", key=f"-HIDE_{index}-"), sg.Button("显示行", key=f"-SHOW_{index}-", visible=False) ] return sg.Frame(f"行 {index}", create_row_inner(), key=f"-ROW_FRAME_{index}-") # 隐藏行时直接操作Frame if event.startswith("-HIDE_"): idx = int(event.split("_")[1]) window[f"-ROW_FRAME_{idx}-"].update(visible=False) window[f"-SHOW_{idx}-"].update(visible=True) # 过滤时检查Frame可见性 if event == "-GENERATE-": valid_mappings = {} for idx in range(row_index): frame = window[f"-ROW_FRAME_{idx}-"] # 先检查Frame是否可见 if not frame.visible: continue # 后续检查逻辑同方案一 pass
关键说明
- 控件key的命名必须有规律(比如带索引后缀),这样才能批量遍历验证
- 过滤逻辑必须包含三个检查条件:复选框勾选、控件可见、输入非空
- 方案一适合快速实现,方案二适合复杂布局的行管理
内容的提问来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

