337 lines
11 KiB
Markdown
337 lines
11 KiB
Markdown
# Step1Panel UI 联动逻辑优化说明
|
||
|
||
## 📋 修改概览
|
||
|
||
本次优化针对 Step1Panel(水域掩膜生成步骤)的 UI 联动逻辑进行了深度重构,主要解决了:
|
||
1. ✅ 输出掩膜组件与单选按钮的深度绑定
|
||
2. ✅ 路径显示的斜杠混用问题
|
||
3. ✅ 底层运行逻辑的兼容性
|
||
|
||
---
|
||
|
||
## 🎯 核心改进
|
||
|
||
### 1. 输出掩膜的显示/隐藏与单选按钮深度绑定
|
||
|
||
#### 修改位置:`Step1Panel.update_ui_state()`
|
||
|
||
**原逻辑问题**:
|
||
- 输出掩膜在两种模式下都显示,不符合业务逻辑
|
||
- "使用现有掩膜文件"时不需要指定输出路径
|
||
|
||
**新逻辑**:
|
||
```python
|
||
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 下的 `\` 和 `/` 混用
|
||
|
||
```python
|
||
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()`
|
||
|
||
**原逻辑问题**:
|
||
- 开机时直接填充路径,不考虑当前选择的模式
|
||
- 没有斜杠格式化
|
||
|
||
**新逻辑**:
|
||
```python
|
||
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
|
||
- "使用现有掩膜"模式下传递空路径可能导致底层错误
|
||
|
||
**新逻辑**:
|
||
```python
|
||
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自动生成"模式:传递用户选择的路径
|
||
|
||
**底层兼容性**:
|
||
```python
|
||
# 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()` 填充输出掩膜路径
|
||
- 不考虑当前的单选按钮状态
|
||
|
||
**新逻辑**:
|
||
```python
|
||
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:用户点击"独立运行此步骤"
|
||
|
||
#### 当前选择:"使用现有掩膜文件"
|
||
```python
|
||
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自动生成"
|
||
```python
|
||
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** 行
|
||
|
||
---
|
||
|
||
## 🎯 优化效果
|
||
|
||
### 用户体验提升
|
||
1. ✅ UI 更简洁:不需要的组件自动隐藏
|
||
2. ✅ 路径一致性:所有路径显示统一使用正斜杠
|
||
3. ✅ 自动化程度提高:切换模式时自动填充/清空路径
|
||
|
||
### 代码质量提升
|
||
1. ✅ 职责分离:主窗口不直接操作子面板的路径填充
|
||
2. ✅ 逻辑内聚:Step1Panel 内部自主管理显示和路径
|
||
3. ✅ 兼容性保障:底层 Pipeline 不会收到无效的 output_path
|
||
|
||
### 维护性提升
|
||
1. ✅ 新增 `_auto_fill_output_path()` 方法,单一职责
|
||
2. ✅ 路径格式化逻辑集中在一处,便于修改
|
||
3. ✅ 注释清晰,说明了各模式下的行为
|
||
|
||
---
|
||
|
||
## 🔧 后续可能的扩展
|
||
|
||
如果其他步骤也有类似的路径填充需求,可以考虑:
|
||
1. 提取公共方法 `format_path_separator(path)` 到工具类
|
||
2. 在 `FileSelectWidget` 类中增加路径格式化的内置支持
|
||
3. 为所有路径输入框添加统一的验证和格式化逻辑
|
||
|
||
---
|
||
|
||
**文档生成时间**: 2026-05-06
|
||
**修改人员**: DXC
|
||
**关联提交**: (待提交)
|