11 KiB
11 KiB
Step1Panel UI 联动逻辑优化说明
📋 修改概览
本次优化针对 Step1Panel(水域掩膜生成步骤)的 UI 联动逻辑进行了深度重构,主要解决了:
- ✅ 输出掩膜组件与单选按钮的深度绑定
- ✅ 路径显示的斜杠混用问题
- ✅ 底层运行逻辑的兼容性
🎯 核心改进
1. 输出掩膜的显示/隐藏与单选按钮深度绑定
修改位置:Step1Panel.update_ui_state()
原逻辑问题:
- 输出掩膜在两种模式下都显示,不符合业务逻辑
- "使用现有掩膜文件"时不需要指定输出路径
新逻辑:
def update_ui_state(self):
"""根据选择的掩膜生成方式更新UI状态(使用显示/隐藏控制)"""
use_ndwi = self.use_ndwi_radio.isChecked()
# 动态显示/隐藏组件
if use_ndwi:
# 使用NDWI模式:隐藏掩膜文件,显示NDWI参数和输出掩膜
self.mask_file.setVisible(False)
self.ndwi_group.setVisible(True)
self.output_file.setVisible(True) # 显示输出掩膜路径
# 当切换到NDWI模式时,如果工作目录已设置,自动填充输出路径
if hasattr(self, 'work_dir') and self.work_dir:
self._auto_fill_output_path()
else:
# 使用现有掩膜模式:显示掩膜文件,隐藏NDWI参数和输出掩膜
self.mask_file.setVisible(True)
self.ndwi_group.setVisible(False)
self.output_file.setVisible(False) # 隐藏输出掩膜路径
# 参考影像在两种模式下都显示
self.img_file.setVisible(True)
行为说明:
| 模式 | 掩膜文件 | NDWI参数组 | 输出掩膜 | 参考影像 |
|---|---|---|---|---|
| 使用现有掩膜文件 | ✅ 显示 | ❌ 隐藏 | ❌ 隐藏 | ✅ 显示 |
| 使用NDWI自动生成 | ❌ 隐藏 | ✅ 显示 | ✅ 显示 | ✅ 显示 |
2. 修复路径斜杠混用问题
修改位置 1:Step1Panel._auto_fill_output_path() (新增方法)
核心改进:统一使用正斜杠 /,避免 Windows 下的 \ 和 / 混用
def _auto_fill_output_path(self):
"""
自动填充输出掩膜路径(仅在NDWI模式下)
确保路径使用正斜杠,避免斜杠混用
"""
if not hasattr(self, 'work_dir') or not self.work_dir:
return
# 生成输出掩膜的完整路径
output_dir = os.path.join(self.work_dir, "1_water_mask")
os.makedirs(output_dir, exist_ok=True) # 确保目录存在
# 统一使用正斜杠,避免 \ 和 / 混用
default_output_path = os.path.join(output_dir, "water_mask_out.dat").replace('\\', '/')
self.output_file.set_path(default_output_path)
关键技术点:
- 使用
os.path.join()构建路径(适配不同操作系统) - 最终通过
.replace('\\', '/')统一转换为正斜杠 - 在界面显示前完成转换,确保用户看到的路径一致
修改位置 2:Step1Panel.update_work_directory()
原逻辑问题:
- 开机时直接填充路径,不考虑当前选择的模式
- 没有斜杠格式化
新逻辑:
def update_work_directory(self, work_dir):
"""
保存工作目录引用,用于后续自动填充路径
Args:
work_dir: 工作目录路径
"""
if not work_dir:
return
# 保存工作目录引用
self.work_dir = work_dir
# 如果当前选中的是NDWI模式,立即填充输出路径
if self.use_ndwi_radio.isChecked():
self._auto_fill_output_path()
改进说明:
- 只保存工作目录引用,不立即填充
- 仅在 NDWI 模式下才调用
_auto_fill_output_path() - 配合
update_ui_state()中的切换触发逻辑
3. 底层运行逻辑的兼容性保障
修改位置:Step1Panel.get_config()
原逻辑问题:
- 无论哪种模式,都传递
output_path给底层 Pipeline - "使用现有掩膜"模式下传递空路径可能导致底层错误
新逻辑:
def get_config(self):
"""获取配置"""
use_ndwi = self.use_ndwi_radio.isChecked()
config = {
'mask_path': None if use_ndwi else self.mask_file.get_path(),
'use_ndwi': use_ndwi,
'ndwi_threshold': self.ndwi_threshold.value()
}
# 参考影像路径(两种模式都可能需要)
img_path = self.img_file.get_path()
if img_path:
config['img_path'] = img_path
# 输出路径:仅在NDWI模式下有效
if use_ndwi:
output_path = self.output_file.get_path()
if output_path:
config['output_path'] = output_path
else:
# 使用现有掩膜时,不传递output_path,避免底层错误尝试保存文件
config['output_path'] = None
return config
关键改进:
- 根据
use_ndwi模式动态决定是否传递output_path - "使用现有掩膜"模式:强制
output_path = None - "NDWI自动生成"模式:传递用户选择的路径
底层兼容性:
# Pipeline 中的处理逻辑(已在之前的提交中实现)
def step1_generate_water_mask(..., output_path: Optional[str] = None):
if use_ndwi:
if output_path:
ndwi_output_path = output_path # 使用用户指定路径
else:
ndwi_output_path = str(self.water_mask_dir / "water_mask_from_ndwi.dat")
4. 主窗口初始化逻辑优化
修改位置:WaterQualityGUI._auto_fill_output_paths()
原逻辑问题:
- 开机时直接调用
set_path()填充输出掩膜路径 - 不考虑当前的单选按钮状态
新逻辑:
def _auto_fill_output_paths(self):
"""
根据工作目录自动填充各步骤的输出路径
注意:Step1 的输出路径由 update_work_directory() 根据模式自动控制
"""
if not self.work_dir:
return
# Step1: 只传递工作目录引用,不直接填充路径
# 路径填充由 Step1Panel 根据单选按钮状态自动控制
if hasattr(self, 'step1_panel'):
self.step1_panel.update_work_directory(self.work_dir)
改进说明:
- 主窗口只传递工作目录引用
- Step1Panel 内部根据模式自主决定是否填充路径
- 解耦主窗口和子面板的逻辑依赖
🔄 完整的交互流程
场景 1:开机启动(默认选中"使用现有掩膜文件")
1. 主窗口启动 → QTimer.singleShot(100) 延迟弹窗
2. 用户选择工作目录 D:\work
3. _auto_fill_output_paths() 调用 step1_panel.update_work_directory(work_dir)
4. Step1Panel.update_work_directory() 保存 self.work_dir = "D:\work"
5. 检查当前模式:use_existing_radio.isChecked() = True
6. 不调用 _auto_fill_output_path(),输出掩膜保持隐藏
7. 用户看到的界面:
✅ 掩膜文件输入框(显示)
✅ 参考影像输入框(显示)
❌ NDWI参数组(隐藏)
❌ 输出掩膜输入框(隐藏)
场景 2:用户切换到"使用NDWI自动生成"
1. 用户点击"使用NDWI自动生成"单选按钮
2. 触发 toggled 信号 → update_ui_state()
3. use_ndwi = True
4. 执行显示/隐藏逻辑:
- self.mask_file.setVisible(False) # 隐藏掩膜文件
- self.ndwi_group.setVisible(True) # 显示NDWI参数组
- self.output_file.setVisible(True) # 显示输出掩膜
5. 检查工作目录:hasattr(self, 'work_dir') = True
6. 调用 self._auto_fill_output_path()
7. 生成路径:
output_dir = os.path.join("D:\work", "1_water_mask")
path = os.path.join(output_dir, "water_mask_out.dat")
formatted_path = path.replace('\\', '/')
# 结果:D:/work/1_water_mask/water_mask_out.dat
8. 自动填充到输出掩膜输入框
9. 用户看到的界面:
❌ 掩膜文件输入框(隐藏)
✅ 参考影像输入框(显示)
✅ NDWI参数组(显示)
✅ 输出掩膜输入框(显示,已填充:D:/work/1_water_mask/water_mask_out.dat)
场景 3:用户点击"独立运行此步骤"
当前选择:"使用现有掩膜文件"
config = {
'mask_path': "D:/data/existing_mask.dat", # 用户选择的现有掩膜
'use_ndwi': False,
'ndwi_threshold': 0.4,
'img_path': "D:/data/image.dat",
'output_path': None # ✅ 强制为 None,不尝试保存
}
当前选择:"使用NDWI自动生成"
config = {
'mask_path': None, # NDWI模式不需要现有掩膜
'use_ndwi': True,
'ndwi_threshold': 0.4,
'img_path': "D:/data/image.dat",
'output_path': "D:/work/1_water_mask/water_mask_out.dat" # ✅ 传递输出路径
}
✅ 测试检查点
UI 显示测试
- 开机启动后,默认选中"使用现有掩膜文件",输出掩膜输入框应隐藏
- 切换到"使用NDWI自动生成",输出掩膜输入框应显示,并自动填充路径
- 切换回"使用现有掩膜文件",输出掩膜输入框应再次隐藏
- 所有自动填充的路径应使用正斜杠
/,无\混用
路径格式测试
- 工作目录:
D:\work→ 输出路径应显示为:D:/work/1_water_mask/water_mask_out.dat - 工作目录:
C:\Users\Test\Documents→ 输出路径应显示为:C:/Users/Test/Documents/1_water_mask/water_mask_out.dat
运行逻辑测试
- "使用现有掩膜"模式运行:验证
config['output_path'] == None - "NDWI自动生成"模式运行:验证
config['output_path']为有效路径字符串 - 底层 Pipeline 接收
output_path=None时不报错
📝 代码修改总结
| 文件 | 修改内容 | 行数变化 |
|---|---|---|
src/gui/water_quality_gui.py |
Step1Panel.update_ui_state() | +6 / -3 |
src/gui/water_quality_gui.py |
Step1Panel.update_work_directory() | +10 / -8 |
src/gui/water_quality_gui.py |
Step1Panel._auto_fill_output_path() (新增) | +15 / 0 |
src/gui/water_quality_gui.py |
Step1Panel.get_config() | +12 / -6 |
src/gui/water_quality_gui.py |
WaterQualityGUI._auto_fill_output_paths() | +3 / -4 |
总计:约 +46 / -21 行
🎯 优化效果
用户体验提升
- ✅ UI 更简洁:不需要的组件自动隐藏
- ✅ 路径一致性:所有路径显示统一使用正斜杠
- ✅ 自动化程度提高:切换模式时自动填充/清空路径
代码质量提升
- ✅ 职责分离:主窗口不直接操作子面板的路径填充
- ✅ 逻辑内聚:Step1Panel 内部自主管理显示和路径
- ✅ 兼容性保障:底层 Pipeline 不会收到无效的 output_path
维护性提升
- ✅ 新增
_auto_fill_output_path()方法,单一职责 - ✅ 路径格式化逻辑集中在一处,便于修改
- ✅ 注释清晰,说明了各模式下的行为
🔧 后续可能的扩展
如果其他步骤也有类似的路径填充需求,可以考虑:
- 提取公共方法
format_path_separator(path)到工具类 - 在
FileSelectWidget类中增加路径格式化的内置支持 - 为所有路径输入框添加统一的验证和格式化逻辑
文档生成时间: 2026-05-06
修改人员: DXC
关联提交: (待提交)