[英]wxPython - How to sort ListCtrl column items?
I am trying to create an CheckListCtrl where you could sort all the Data in an column by clicking on its header. 我正在尝试创建一个CheckListCtrl,您可以在其中通过单击其标题来对列中的所有数据进行排序。
In the basic example of my code i will post below i setup "rows" as a List of Tuples because in my final version the ListCtrl will show the result of an SQLite Query. 在我代码的基本示例中,我将在下面以“元组列表”的形式发布“行”,因为在我的最终版本中,ListCtrl将显示SQLite查询的结果。
The problem i have with my code so far: 到目前为止,我的代码存在问题:
I used self.itemDataMap = rows
wrong i think, i get this error message if i try to sort: TypeError: list indices must be integers or slices, not tuple
. 我使用
self.itemDataMap = rows
错误,我认为,如果我尝试排序,则会收到以下错误消息: TypeError: list indices must be integers or slices, not tuple
。 So how do i use it with an List of Tuples and not with an Dictionary? 那么如何将其与元组列表而不是字典一起使用?
import wx
import wx.lib.mixins.listctrl as listmix
from wx.lib.agw import ultimatelistctrl as ULC
APPNAME='Sortable Ultimate List Ctrl'
APPVERSION='1.0'
MAIN_WIDTH=300
MAIN_HEIGHT=300
class TestUltimateListCtrlPanel(wx.Panel, listmix.ColumnSorterMixin):
def __init__(self, parent):
wx.Panel.__init__(self, parent, -1, style=wx.WANTS_CHARS, size=(MAIN_WIDTH,MAIN_HEIGHT))
self.index = 0
self.list_ctrl = ULC.UltimateListCtrl(self, -1, agwStyle=ULC.ULC_REPORT|ULC.ULC_HAS_VARIABLE_ROW_HEIGHT)
self.list_ctrl.InsertColumn(0, "Make")
self.list_ctrl.InsertColumn(1, "Model")
self.list_ctrl.InsertColumn(2, "Year")
self.list_ctrl.InsertColumn(3, "Color")
rows = [("Ford", "Taurus", "1996", "Blue"),
("Nissan", "370Z", "2010", "Green"),
("Porche", "911", "2009", "Red")
]
index = 0
for data in rows:
pos=self.list_ctrl.InsertStringItem(index, data[0])
self.list_ctrl.SetStringItem(index, 1, data[1])
self.list_ctrl.SetStringItem(index, 2, data[2])
self.list_ctrl.SetStringItem(index, 3, data[3])
self.list_ctrl.SetItemData(index, rows[index])
index += 1
self.itemDataMap = rows
listmix.ColumnSorterMixin.__init__(self, 3)
self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick, self.list_ctrl)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.list_ctrl, 1, wx.ALL|wx.EXPAND, 5)
self.SetSizer(sizer)
def GetListCtrl(self):
return self.list_ctrl
def OnColClick(self, event):
pass
class MyForm(wx.Frame):
def __init__(self):
wx.Frame.__init__(self,None,wx.ID_ANY,'%s v%s' % (APPNAME,APPVERSION),size=(MAIN_WIDTH,MAIN_HEIGHT),style=wx.MINIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN)
panel = TestUltimateListCtrlPanel(self)
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()
First let me quote the documentation of wx.lib.mixins.listctrl.ColumnSorterMixin
: 首先让我引用
wx.lib.mixins.listctrl.ColumnSorterMixin
的文档:
The combined class must have an attribute named itemDataMap that is a dictionary mapping the data values to a sequence of objects representing the values in each column.
组合的类必须具有一个名为itemDataMap的属性,该属性是将数据值映射到表示每一列中的值的对象序列的字典。 These values are compared in the column sorter to determine sort order.
在列排序器中比较这些值以确定排序顺序。
That's hardly understandable. 这很难理解。
What it means is, that .itemDataMap
hs to be a dictionary , where the key of each entry are the data of a row. 这意味着
.itemDataMap
必须是字典 ,其中每个条目的键是一行的数据。 The value is a list: 该值是一个列表:
self.itemDataMap = {}
for rowIndex, data in enumerate(rows):
self.itemDataMap[data] = []
Each element of the immer list is associated to a column and is used to sort the elements of a column. 浸入式列表的每个元素都与一列关联,并用于对一列的元素进行排序。 If the rows should be sorted in alphabetic order dependent of the values of a column, then the value which is associated to the column index (in the dictionary of a row) can be the value of the filed:
如果应根据列的值按字母顺序对行进行排序,则与列索引相关联的值(在行的字典中)可以是字段的值:
self.itemDataMap[data] = []
for coldata in data:
self.itemDataMap[data] += coldata
Since the rows are already organised in a list, the rows can be use directly: 由于行已在列表中组织,因此可以直接使用行:
self.itemDataMap[data] = data
The same can be achieved by 同样可以通过
self.itemDataMap = {data : data for data in rows}
Note, the keys of .itemDataMap
have to correspond to the data of a row, which is set by SetItemData()
. 请注意,
.itemDataMap
的键必须与由SetItemData()
设置的行数据相对应。
Since the data of a row are organised in a list 由于行的数据组织在列表中
When the list should be sorted by the values of specific column index col
, then all then elements in .itemDataMap
which are associated to col
are listed and the list is sorted by this elements. 当列表应按特定列索引
col
的值排序时,则列出与col
关联的所有.itemDataMap
元素,然后按此元素对列表进行排序。 You can imagine this like: 您可以像这样想象:
col = ... # integral index of the column
sorted( [values[col] for values in self.itemDataMap.values()] )
Further note, the number of columns is 4: 进一步注意,列数为4:
listmix.ColumnSorterMixin.__init__(self, 3)
listmix.ColumnSorterMixin.__init__(self, 4)
Class TestUltimateListCtrlPanel
: 类
TestUltimateListCtrlPanel
:
class TestUltimateListCtrlPanel(wx.Panel, listmix.ColumnSorterMixin):
def __init__(self, parent):
wx.Panel.__init__(self, parent, -1, style=wx.WANTS_CHARS, size=(MAIN_WIDTH,MAIN_HEIGHT))
self.list_ctrl = ULC.UltimateListCtrl(self, -1, agwStyle=ULC.ULC_REPORT|ULC.ULC_HAS_VARIABLE_ROW_HEIGHT)
self.list_ctrl.InsertColumn(0, "Make")
self.list_ctrl.InsertColumn(1, "Model")
self.list_ctrl.InsertColumn(2, "Year")
self.list_ctrl.InsertColumn(3, "Color")
rows = [("Ford", "Taurus", "1996", "Blue"),
("Nissan", "370Z", "2010", "Green"),
("Porche", "911", "2009", "Red")
]
for rowIndex, data in enumerate(rows):
for colIndex, coldata in enumerate(data):
if colIndex == 0:
self.list_ctrl.InsertStringItem(rowIndex, coldata)
else:
self.list_ctrl.SetStringItem(rowIndex, colIndex, coldata)
self.list_ctrl.SetItemData(rowIndex, data)
self.itemDataMap = {data : data for data in rows}
listmix.ColumnSorterMixin.__init__(self, 4)
self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick, self.list_ctrl)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.list_ctrl, 1, wx.ALL|wx.EXPAND, 5)
self.SetSizer(sizer)
def GetListCtrl(self):
return self.list_ctrl
def OnColClick(self, event):
pass
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.