简体   繁体   English

wxPython-如何对ListCtrl列项目进行排序?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM