Column sorting with the mixin class

One common case for sorting a list control is to give the user the ability to sort a list in report view in any column by clicking on the column. You could do that

□ wx.ListCtrl with ColumnSorterMixiri Lj[[email protected]

Request ID

1 Summary

1 Date A


OS X wheel mouse

2003-10-03 14: Of

1 819559

wxListCtrl column widths in wxLC_ICON mode

2003-10-07 13:3£


Wishlist - wxStaticText that takes fonts, colors, etc.

2003-11-20 21:li

Q 846362

Wishlist - Crossplatform wxRichText Widget

2003-11-20 21iï.2X.


wxPostscriptDC with floating point coordinates

2003-11-20 21:22

1 846363

Wishlist - Better wxString Formatting

2003-11-20 21:22


Wishlist - wxDbGetConnection return value

2003-11-20 21:2]

Q 846367

Less flicker when resizing a window

2003-11-20 21:2'


wxTextCtrl - disable auto-scrolling

2003-11-20 21:2:

Q 846369

wxGird - auto-scrolling

2003-11-20 21:2É

H 846372

Hooks for standard remote events

2003-11-20 21:2;

H 846370

wxDial - dial widget

2003-11-20 21:2;

Q 846373

Scrolling improvements

2003-11-20 21:2«


wxToolBar - return tool at position

2003-11-20 21:2i

1 846375


2003-11-20 21:3C

Q 852379

wxGrid row/col size limits

2003-12-01 15:4;

1 855902

virtual window classes

2003-12-07 12:3i

S 863301

wxTextCtrl - edit mode

2003-12-19 17:4i

1 863306

wxGrid - ThawfFreeze columnfrow

2003-12-19 17:5'



The column sorter mixin in action—notice the arrow in the date column indicating sort direction with the Sortltems() mechanism, but it would be somewhat complex to keep track of the columns. Fortunately, a wxPython mixin class, called ColumnSorter-Mixin, manages the information for you, and lives in the module wx.lib.mixins. listctrl. Figure 13.5 displays the column sorting using the mixin class.

Declare the mixin just like any other Python multiple inheritance declaration, as in the following.

import wx.lib.mixins.listctrl as listmix class ListCtrlPanel(wx.Panel, listmix.ColumnSorterMixin):

wx.Panel._init_(self, parent, -1, style=wx.WANTS_CHARS)

self.list = TestListCtrl(self, tID) self.itemDataMap = musicdata listmix.ColumnSorterMixin._init_(self, 3)

Notice that the mixin is not extending the list control itself, although it could do that as well, but it's more likely that you are creating a custom panel. Instead, it's extending the containing panel. The panel gets code to manage the sorting and to bind the mouse click event in the column header. Listing 13.4 displays a completed column sorter example.

Listing 13.4 A report list with the column sorter mixin import wx import wx.lib.mixins.listctrl import sys, glob, random import data class DemoFrame(wx.Frame, wx.lib.mixins.listctrl.ColumnSorterMixin): <—, def _init_(self): Deriving from the mixin |

"wx.ListCtrl with ColumnSorterMixin", size=(600,400))

il = wx.ImageList(16,16, True)

for name in glob.glob("smicon??.png"):

bmp = wx.Bitmap(name, wx.BITMAP_TYPE_PNG) il_max = il.Add(bmp)

I Adding arrows to the image list self.up = il.AddWithColourMask <1—1 " ^

wx.Bitmap("sm_up.bmp", wx.BITMAP_TYPE_BMP), "blue") self.dn = il.AddWithColourMask(

wx.Bitmap("sm_down.bmp", wx.BITMAP_TYPE_BMP), "blue")

self.list = wx.ListCtrl(self, -1, style=wx.LC_REPORT)

self.list.AssignImageList(il, wx.IMAGE_LIST_SMALL) \

for col, text in enumerate(data.columns):

self.list.InsertColumn(col, text)

111 Creating data maps for item in data.rows: 1

index = self.list.InsertStringItem(sys.maxint, item[0]) for col, text in enumerate(item[1:]):

self.list.SetStringItem(index, col+1, text) self.list.SetItemData(index, index) < self.itemDataMap[index] = item img = random.randint(0, il_max) self.list.Set!temImage(index, img, img)

Associating data with maps self.list.SetColumnWidth(0, 120)

self.list.SetColumnWidth(1, wx.LIST_AUTOSIZE)

self.list.SetColumnWidth(2, wx.LIST_AUTOSIZE)

self.list.SetColumnWidth(3, wx.LIST_AUTOSIZE_USEHEADER)

wx.lib.mixins.listctrl.ColumnSorterMixin._init_(self, len(data.columns))

Initializing the columns sorter def GetListCtrl(self): return self.list def GetSortImages(self):

return (self.dn, self.up)

app = wx.PySimpleApp() frame = DemoFrame() frame.Show() app.MainLoop()

For the mixin to work, you need to perform the following in your own panel class:

1 The class that extends ColumnSorterMixin must have a method called GetListCtrl() which returns the actual list control to be sorted. This method is used by the mixin to get a reference to the control.

2 In the__init__() method of the extending class, you must create the list control referred to by GetListCtrl() before you call the _init_()

method of the ColumnSorterMixin. The_init_() method of the mixin takes one argument, an integer representing the number of columns in the list control.

3 You must use SetListData() to set a unique data value for each row in the list. This can be (and most likely will be) nothing more than an index into a more complex data structure.

4 The extending class must have an attribute called itemDataMap. This attribute must be a dictionary. The keys to this dictionary are the data values set by SetListData(). The values are a tuple of the values you want to use to sort by each column. (Typically, this will just be the text in each column). In other words, the itemDataMap essentially replicates the data in the control in a form that is easy to sort.

In a typical usage of ColumnSorterMixin, you will either create the itemDataMap as you add items to your list control or you will create the itemDataMap first, and use that to build the list control itself.

Although the setup can be complex, the ColumnSorterMixin is a great choice for a common sorting use case.

Was this article helpful?

0 0

Post a comment