Add sorting capability for "选择" and "材料名称" columns in the CheckboxTreeview: - Click column header to cycle through: asc (↑) → desc (↓) → unsort - Sort "选择" column by checkbox state (checked/unchecked) - Sort "材料名称" column alphabetically - Preserve checkbox states during sorting using move() instead of delete+insert - Separate event handlers for cell clicks and heading clicks Implementation details: - Added 6 new helper methods to CheckboxTreeview class - Store original headings to properly display sort arrows - Use identify_region() to distinguish between cell and heading clicks - Column index conversion (#1/#2) to column identifiers The sorting is a pure frontend feature with no database changes. Available to all users without permission restrictions. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
3.4 KiB
3.4 KiB
排序功能快速参考
用户使用指南
如何使用排序功能
-
点击列头排序
- 点击"选择"或"材料名称"列头
- 第一次点击:升序排列(显示 ↑)
- 第二次点击:降序排列(显示 ↓)
- 第三次点击:取消排序(箭头消失)
-
切换排序列
- 点击其他可排序列的列头
- 原列的排序箭头自动消失
- 新列显示排序箭头
-
排序时复选框状态
- 排序操作不会改变复选框的选中状态
- 所有项目的复选框状态在排序后保持不变
支持的列
✅ 可排序:
- 选择
- 材料名称
❌ 不可排序:
- 材料代码
- 规格
- 型号
- 负责人
开发者参考
核心方法
| 方法 | 功能 |
|---|---|
_store_original_headings() |
存储原始列标题 |
_get_column_id_from_column_index() |
列索引转列标识符 |
_on_heading_click() |
处理表头点击事件 |
_toggle_sort() |
切换排序状态 |
_sort_by_column() |
执行排序操作 |
_update_heading_display() |
更新列标题显示 |
排序状态变量
self.sort_column = None # 当前排序列('选择' 或 '材料名称')
self.sort_direction = None # 排序方向('asc', 'desc', 或 None)
self.sortable_columns = ["选择", "材料名称"] # 可排序列白名单
self.original_headings = {} # 原始列标题文本
扩展排序到其他列
如果要添加新的可排序列,修改 sortable_columns 列表:
self.sortable_columns = ["选择", "材料名称", "材料代码", "负责人"]
然后在 _sort_by_column() 方法中添加对应的排序逻辑:
elif column_id == "材料代码":
items_data.sort(
key=lambda x: str(x['values'][2]) if len(x['values']) > 2 else "",
reverse=(direction == 'desc')
)
elif column_id == "负责人":
items_data.sort(
key=lambda x: str(x['values'][5]) if len(x['values']) > 5 else "",
reverse=(direction == 'desc')
)
排序逻辑
"选择"列:
# 按复选框状态排序
items_data.sort(key=lambda x: x['checked'], reverse=(direction == 'desc'))
"材料名称"列:
# 按字符串排序
items_data.sort(
key=lambda x: str(x['values'][1]) if len(x['values']) > 1 else "",
reverse=(direction == 'desc')
)
保持复选框状态的关键
使用 move() 方法而不是 delete() + insert():
# ✅ 正确:保留复选框状态
self.move(item_data['item_id'], '', 'end')
# ❌ 错误:会丢失复选框状态
# self.delete(item)
# self.insert("", tk.END, values=values)
故障排查
问题:点击列头没有反应
可能原因:
- 点击的不是可排序列
- 表格为空
解决方法:
- 确保点击的是"选择"或"材料名称"列
- 确保表格中有数据
问题:排序后复选框状态丢失
可能原因:
使用了 delete() + insert() 而不是 move()
解决方法:
检查 _sort_by_column() 方法中使用的是 move() 而不是 delete()
问题:排序箭头显示不正确
可能原因: 原始列标题没有正确存储
解决方法:
检查 _store_original_headings() 是否被正确调用(延迟100ms)
测试命令
# 运行排序功能测试
python tests/test_sorting.py
# 语法检查
python -m py_compile gui/material_validation_tab.py