wxPython Ultimate List Control箭头滚动异常及数字列排序求助
问题1:箭头键滚动抛出TypeError的解决方案
错误根源是**ColumnSorterMixin与UltimateListCtrl的ItemData类型不兼容**——你将元组(d,c)作为SetItemData的值,而ColumnSorterMixin期望ItemData是整数索引,滚动逻辑在处理非整数ItemData时会产生浮点数参数,导致_ScrolledWindowBase.Scroll()调用失败。
修正步骤:
- 重构
itemDataMap,将键改为整数索引(对应列表项的index),值存储排序所需的原始数据(字符串和整数)。 - 将
SetItemData的参数改为整数index,而非元组。
修改数据填充部分的代码:
self.itemDataMap = {} for line in f.readlines(): #(display, CR, monster) (d, c, m) = line.split(":") cr_val = int(c.strip()) # 转换为整数,用于排序和后续编辑 self.monsterDict[index] = [m.strip(), d, cr_val] # 新增存储CR整数 self.listCtrl.InsertStringItem(index, d) # 格式化CR显示(保持补0逻辑) cr_display = f"{cr_val:02d}" if cr_val <10 else str(cr_val) self.listCtrl.SetStringItem(index, 1, cr_display) self.itemDataMap[index] = [d, cr_val] # 键为index,值为排序字段 self.listCtrl.SetItemData(index, index) # ItemData设为整数index index+=1
同时删除自定义的OnColClick空方法,因为ColumnSorterMixin已经实现了列点击排序逻辑,空方法会覆盖默认行为导致异常。
问题2:CR列支持整数输入与数值排序
2.1 开启列编辑功能
修改UltimateListCtrl的创建代码,添加ULC_EDIT_LABELS样式:
self.listCtrl = ULC.UltimateListCtrl(self, -1, agwStyle=ULC.ULC_REPORT | ULC.ULC_EDIT_LABELS)
2.2 绑定编辑事件,限制整数输入
添加以下事件绑定和处理方法:
# 在__init__中添加绑定 self.listCtrl.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.OnBeginCREdit) self.listCtrl.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEndCREdit) # 编辑开始时,仅允许CR列(索引1)被编辑 def OnBeginCREdit(self, event): if event.GetColumn() != 1: event.Veto() # 禁止编辑其他列 else: event.Skip() # 编辑结束时,验证输入是否为整数 def OnEndCREdit(self, event): if event.GetColumn() !=1: event.Veto() return new_val = event.GetLabel().strip() if not new_val.isdigit(): wx.MessageBox("请输入有效的整数CR值", "输入错误", wx.OK | wx.ICON_ERROR) event.Veto() return # 更新显示和数据 cr_int = int(new_val) item_idx = event.GetIndex() # 格式化显示(补0) cr_display = f"{cr_int:02d}" if cr_int <10 else str(cr_int) self.listCtrl.SetStringItem(item_idx, 1, cr_display) # 更新monsterDict和itemDataMap self.monsterDict[item_idx][2] = cr_int self.itemDataMap[item_idx][1] = cr_int event.Skip()
2.3 实现数值排序
重写SortListItems方法,针对CR列使用整数排序逻辑:
# 重写SortListItems方法,自定义排序逻辑 def SortListItems(self, col, ascending): # 获取当前所有项的索引 items = list(self.itemDataMap.keys()) # 根据列选择排序键 if col == 1: # CR列按整数排序 items.sort(key=lambda x: self.itemDataMap[x][1], reverse=not ascending) else: # Monster列按字符串排序 items.sort(key=lambda x: self.itemDataMap[x][0], reverse=not ascending) # 重新排列列表项 self.listCtrl.ReorderItems(items) # 更新排序状态 self._colSort = col self._colAscending = ascending
额外优化建议
- 移除对
listCtrl的SetMaxSize和SetMinSize设置,让sizer自动管理控件大小,避免滚动区域计算异常。 - 文件操作使用
with语句,避免资源泄漏:with open(self.refSheet, "r") as f: for line in f.readlines(): # 处理逻辑...
内容的提问来源于stack exchange,提问作者Joseph_the_Levi
相关产品推荐
相关产品推荐

