# CheckboxTreeview 排序功能实施总结 ## 实施日期 2026-02-24 ## 功能概述 为物料校验界面的校验结果表格添加了排序功能,支持对"选择"和"材料名称"列进行升序、降序排序,并可取消排序。 ## 修改文件 - `D:\python\playwrite\gui\material_validation_tab.py` ## 修改内容 ### 1. CheckboxTreeview.__init__ 方法(第35-60行) **新增变量**: ```python # 排序状态 self.sort_column = None # 当前排序列的列标识符 self.sort_direction = None # 'asc', 'desc', 或 None self.sortable_columns = ["选择", "材料名称"] # 可排序的列白名单 self.original_headings = {} # 存储原始列标题文本(不含箭头) # 存储原始列标题(延迟执行以确保标题已设置) self.after(100, self._store_original_headings) # 绑定表头点击事件 self.bind("", self._on_heading_click) ``` ### 2. CheckboxTreeview._on_click 方法(第62-83行) **修改内容**: - 添加注释说明仅处理单元格点击,不处理表头点击 - 确保与表头点击事件分离,避免冲突 ### 3. 新增方法 #### _store_original_headings(第142-145行) 存储原始列标题文本,避免排序箭头影响后续操作。 #### _get_column_id_from_column_index(第147-160行) 将列索引('#1', '#2')转换为列标识符('选择', '材料名称')。 #### _on_heading_click(第162-172行) 处理表头点击事件,触发排序操作。仅对可排序列("选择"、"材料名称")生效。 #### _toggle_sort(第174-204行) 切换排序状态的核心方法: - 同一列:asc → desc → None(循环) - 不同列:重置为升序 - 调用排序方法并更新表头显示 #### _sort_by_column(第206-237行) 执行实际排序操作: - 收集所有项目的数据和复选框状态 - 根据列类型使用不同的排序逻辑 - 使用 `move()` 方法保留项目ID和复选框状态 **排序逻辑**: - **"选择"列**: 按复选框状态排序(False 未选中在前 → True 选中在前) - **"材料名称"列**: 按字符串字母顺序排序 #### _update_heading_display(第239-248行) 更新列标题显示: - 排序列:显示原始标题 + 箭头(↑ 升序,↓ 降序) - 非排序列:显示原始标题 ## 排序行为 ### "选择"列 - **升序 (↑)**: 未选中 (☐) → 选中 (☑) - **降序 (↓)**: 选中 (☑) → 未选中 (☐) ### "材料名称"列 - **升序 (↑)**: A → Z 字母顺序 - **降序 (↓)**: Z → A 字母顺序 ### 点击循环 1. 第一次点击: 升序(显示 ↑) 2. 第二次点击: 降序(显示 ↓) 3. 第三次点击: 取消排序(移除箭头) ## 技术要点 ### 1. 使用 move() 而非 delete() + insert() - `delete()` 会删除项目及其关联的复选框状态 - `move()` 仅改变项目位置,保留项目ID - 项目ID与 `self.checkboxes` 字典中的复选框状态关联 - 使用 `move()` 可自动保持复选框状态 ### 2. 事件绑定策略 - ``: 现有复选框点击事件(在 `_on_click` 中处理) - ``: 新增的表头点击事件(在 `_on_heading_click` 中处理) - 使用 `identify_region` 区分点击区域("cell" vs "heading") ### 3. 延迟存储原始标题 ```python self.after(100, self._store_original_headings) ``` 确保在 Treeview 标题设置完成后再存储,避免获取空值。 ### 4. 复选框状态保持 排序过程中: 1. 收集所有项目的 `item_id` 和 `checkbox_state` 2. 对数据列表进行排序 3. 使用 `move()` 重新排列项目 4. `self.checkboxes` 字典自动保持正确状态(key 是 item_id) ## 兼容性 ### 向后兼容 - ✅ 所有现有功能保持不变 - ✅ 复选框点击功能正常 - ✅ 全选/取消全选功能正常 - ✅ 复选框状态同步功能正常 - ✅ 双击编辑负责人功能正常 ### 无权限限制 - ✅ 适用于所有用户(管理员和普通用户) - ✅ 无需修改权限控制代码 ## 测试建议 ### 功能测试 1. **"选择"列排序**: - 点击列头 → 未选中项目排到最前面 - 再次点击 → 选中项目排到最前面 - 第三次点击 → 箭头消失 2. **"材料名称"列排序**: - 点击列头 → 按字母 A-Z 升序排列 - 再次点击 → 按字母 Z-A 降序排列 - 第三次点击 → 箭头消失 3. **复选框状态保持**: - 选中几个项目 - 进行排序 - 验证复选框状态保持不变 4. **跨列切换**: - 在"选择"列排序后,点击"材料名称"列 - 验证"选择"列箭头消失,"材料名称"列显示箭头 - 验证按新的列排序 5. **复选框点击兼容性**: - 排序后点击复选框 - 验证复选框状态切换功能正常 ### 边界情况测试 1. **空表格**: 排序不应报错 2. **单行数据**: 排序不应报错 3. **所有项目相同值**: 排序不应改变顺序 4. **中文字符排序**: 验证中文排序正确 5. **动态添加数据**: 排序后添加新数据,验证排序状态保持 ## 风险评估 - **低风险**: 仅影响 CheckboxTreeview 的显示和交互 - **向后兼容**: 所有现有功能保持不变 - **无数据库改动**: 纯前端排序功能 - **可测试性**: 容易手动测试验证 ## 预期效果 用户可以通过点击"选择"或"材料名称"列头,快速对数据进行排序,提高数据查看和分析效率。排序状态通过箭头直观显示,符合常见 UI 交互习惯。 ## 测试文件 已创建测试脚本:`tests/test_sorting.py` 运行测试: ```bash python tests/test_sorting.py ``` ## 后续优化建议 1. 可扩展到其他列的排序(如"负责人"、"材料代码"等) 2. 可添加多列排序功能(按住 Shift 点击第二列) 3. 可添加排序持久化(记住用户的排序偏好)