如何实现wxPython ListCtrl列排序:末列数值排序、前两列文本排序
Got it, the issue here is that the default ColumnSorterMixin treats all column values as strings, so your "year" column gets sorted lexicographically (that's why "11" comes before "2"). To fix this, we need to override how the sorting keys are generated based on which column is being sorted.
Here's the modified code with explanations of the key changes:
import wx import sys from wx.lib.mixins.listctrl import ColumnSorterMixin actresses = { 1 : ('jessica alba', 'pomona', '1'), 2 : ('sigourney weaver', 'new york', '2'), 3 : ('angelina jolie', 'los angeles', '11'), 4 : ('natalie portman', 'jerusalem', '12'), 5 : ('rachel weiss', 'london', '20'), 6 : ('scarlett johansson', 'new york', '22') } class SortedListCtrl(wx.ListCtrl, ColumnSorterMixin): def __init__(self, parent): wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT) # Fix: Pass the number of columns (3) instead of number of items ColumnSorterMixin.__init__(self, 3) self.itemDataMap = actresses def GetListCtrl(self): return self # Add this method to customize sorting keys per column def GetSortKey(self, index, col): # Get the text value of the item in the specified column item_text = self.GetItem(index, col).GetText() # For the last column (year), convert to integer for numeric sorting if col == 2: return int(item_text) # For first two columns, use lowercase text for case-insensitive sort # Remove .lower() if you want case-sensitive sorting return item_text.lower() class Actresses(wx.Frame): def __init__(self, parent, id, title): wx.Frame.__init__(self, parent, id, title, size=(380, 230)) hbox = wx.BoxSizer(wx.HORIZONTAL) panel = wx.Panel(self, -1) self.list = SortedListCtrl(panel) self.list.InsertColumn(0, 'name', width=140) self.list.InsertColumn(1, 'place', width=130) self.list.InsertColumn(2, 'year', wx.LIST_FORMAT_RIGHT, 90) items = actresses.items() for key, data in items: index = self.list.InsertStringItem(sys.maxsize, data[0]) self.list.SetStringItem(index, 1, data[1]) self.list.SetStringItem(index, 2, data[2]) self.list.SetItemData(index, key) hbox.Add(self.list, 1, wx.EXPAND) panel.SetSizer(hbox) self.Centre() self.Show(True) if __name__ == '__main__': app = wx.App() Actresses(None, -1, 'Actresses') app.MainLoop()
Key Changes Explained:
Fixed ColumnSorterMixin Initialization:
The original code passedlen(actresses)(which is 6, the number of data items) toColumnSorterMixin.__init__, but this parameter should be the number of columns (3) so the mixin knows how many columns to handle sorting for.Added GetSortKey Method:
This method overrides the default behavior of the mixin. It checks which column is being sorted:- For column 2 (year), we convert the string value to an integer, so sorting uses numeric order instead of lexicographical.
- For columns 0 and 1 (name/place), we return the lowercase text for case-insensitive sorting. Remove
.lower()if you want case-sensitive text sorting.
Now when you click the "year" column header, it will sort numerically (2 → 11 → 12 → 20 → 22), while the name and place columns still sort as text.
内容的提问来源于stack exchange,提问作者Max

