Files
playwrite/docs/SORTING_QUICK_REFERENCE.md
Misaka_Company 0644bdfb11 feat: add column sorting functionality to material validation table
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>
2026-02-24 15:45:55 +08:00

3.4 KiB
Raw Permalink Blame History

排序功能快速参考

用户使用指南

如何使用排序功能

  1. 点击列头排序

    • 点击"选择"或"材料名称"列头
    • 第一次点击:升序排列(显示 ↑)
    • 第二次点击:降序排列(显示 ↓)
    • 第三次点击:取消排序(箭头消失)
  2. 切换排序列

    • 点击其他可排序列的列头
    • 原列的排序箭头自动消失
    • 新列显示排序箭头
  3. 排序时复选框状态

    • 排序操作不会改变复选框的选中状态
    • 所有项目的复选框状态在排序后保持不变

支持的列

可排序:

  • 选择
  • 材料名称

不可排序:

  • 材料代码
  • 规格
  • 型号
  • 负责人

开发者参考

核心方法

方法 功能
_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)

故障排查

问题:点击列头没有反应

可能原因:

  1. 点击的不是可排序列
  2. 表格为空

解决方法:

  • 确保点击的是"选择"或"材料名称"列
  • 确保表格中有数据

问题:排序后复选框状态丢失

可能原因: 使用了 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