wxPython - 如何在排序后获取选中数据 (listmix.ColumnSorterMixin)

1 投票
1 回答
1183 浏览
提问于 2025-04-18 13:05

我有一些数据存储在字典里,这些数据会显示在一个列表控件(ListCtrl)中。我使用了带复选框的列表混合类(listmix.CheckListCtrlMixin)来选择数据,还用了另一个混合类(listmix.ColumnSorterMixin)来进行排序。

问题是,当我按某一列对数据进行排序后,原来的数据顺序就会改变。这样一来,在我勾选了某些项目后,就找不到原来的数据了,后续操作就很麻烦。

有没有办法获取一个新的“排序后的”字典或者类似的东西呢?

下面是一个示例代码。

import sys
import wx
import  wx.lib.mixins.listctrl  as  listmix

musicdata = {
1  : ( 'Bad English', 'The Price Of Love', 'Rock' ),
2  : ( 'Michael Bolton', 'How Am I Supposed To Live Without You', 'Blues' ),
3  : ( 'Paul Young', 'Oh Girl', 'Rock' ),
4  : ( 'Paula Abdul', 'Opposites Attract', 'Rock' ),
5  : ( 'Richard Marx', 'Should\'ve Known Better', 'Rock' ),
6 : ( 'Rod Stewart', 'Forever Young', 'Rock' ),
7 : ( 'Roxette', 'Dangerous', 'Rock' ),
}

class TestListCtrl( wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.CheckListCtrlMixin ) :

    def __init__( self, parent, ID, pos=wx.DefaultPosition,
              size=wx.DefaultSize, style=0 ) :

        wx.ListCtrl.__init__( self, parent, ID, pos, size, style )

        listmix.ListCtrlAutoWidthMixin.__init__( self )
        listmix.CheckListCtrlMixin.__init__(self)
        self.Bind(wx.EVT_LIST_COL_CLICK, self.OnCheckItem)


    def OnCheckItem(self, data, flag):
        print(data, flag)

class TabPanel( wx.Panel, listmix.ColumnSorterMixin ) :

    def __init__( self, parent  ) :

        wx.Panel.__init__( self, parent=parent, id=wx.ID_ANY )

        self.createAndLayout()

    def createAndLayout( self ) :

        sizer = wx.BoxSizer( wx.VERTICAL )
        self.list = TestListCtrl( self, wx.ID_ANY, style=wx.LC_REPORT
                             | wx.BORDER_NONE
                             | wx.LC_EDIT_LABELS
                             | wx.LC_SORT_ASCENDING )

        sizer.Add( self.list, 1, wx.EXPAND )
        self.populateList()

        self.itemDataMap = musicdata
        listmix.ColumnSorterMixin.__init__( self, 3 )
        self.SetSizer( sizer )
        self.SetAutoLayout( True )

    def populateList( self ) :

        self.list.InsertColumn( 0, 'Artist' )
        self.list.InsertColumn( 1, 'Title', wx.LIST_FORMAT_RIGHT )
        self.list.InsertColumn( 2, 'Genre' )
        items = musicdata.items()

        for key, data in items :
            index = self.list.InsertStringItem( sys.maxint, data[ 0 ] )
            self.list.SetStringItem( index, 1, data[ 1 ] )
            self.list.SetStringItem( index, 2, data[ 2 ] )
            self.list.SetItemData( index, key )

        self.list.SetColumnWidth( 0, wx.LIST_AUTOSIZE )
        self.list.SetColumnWidth( 1, wx.LIST_AUTOSIZE )
        self.list.SetColumnWidth( 2, 100 )

        self.list.SetItemState( 5, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED )

        self.currentItem = 0

    def GetListCtrl( self ) :
        return self.list

class DemoFrame( wx.Frame ) :

     def __init__( self ) :

        wx.Frame.__init__( self, None, wx.ID_ANY, title="Panel Tutorial",
                           size=(600, 300) )

        panel = TabPanel( self )
        self.Show()

app = wx.App()
frame = DemoFrame()
app.MainLoop()

1 个回答

1

根据这个问题的答案:如何按值排序Python字典,我们知道字典本身是不能直接排序的,只能得到一个排序后的字典的表示。

你可以在点击某个列标题后,以排序的顺序获取项目列表,只需在class TestListCtrl中定义一个函数,像这样:

class TestListCtrl( wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.CheckListCtrlMixin ) :

    def __init__( self, parent, ID, pos=wx.DefaultPosition,
              size=wx.DefaultSize, style=0 ) :

        wx.ListCtrl.__init__( self, parent, ID, pos, size, style )

        listmix.ListCtrlAutoWidthMixin.__init__( self )
        listmix.CheckListCtrlMixin.__init__(self)
        self.Bind(wx.EVT_LIST_COL_CLICK, self.OnCheckItem)
        self.Binf(wx.EVT_LIST_COL_CLICK, self.GetSortedOrder)


    def OnCheckItem(self, data, flag):
        print(data, flag)

    def GetSortedOrder(self, event):
        count = self.GetItemCount()
        self.sorted_artists = [self.GetItem(itemId=row, col=0).GetText() for row in xrange(count)]
        print self.sorted_artists

这个GetSortedOrder()方法会创建一个sorted_artists属性,这个属性是一个按顺序排列的艺术家列表,每次你点击任何列标题时,它都会更新。你也可以通过改变列的名称来获取其他值,比如标题或类型。如果你想的话,可以用这个来和原始字典进行比较,然后创建一个新的字典。

撰写回答