天天看點

wxpython wx listctrl_wxPython - ListCtrl清單排序

13.4.2 如何對清單排序?

在wxPython中有三個有用的方法可以對清單進行排序,在這一節,我們将按照從易到難的順序來讨論。

在建立的時候告訴清單去排序

對一個清單控件排序的最容易的方法,是在構造函數中告訴該清單控件對項目進行排序。你可以通過使用樣式标記wx.LC_SORT_ASCENDING或wx.LC_SORT_DESCENDING來實作。這兩個标記導緻了清單在初始顯示的時候被排序,并且在Windows上,當新的項目被添加時,依然遵循所樣式标記來排序。對于每個清單項的資料的排序,是基于其字元串文本的,隻是簡單的對字元串進行比較。如果清單是報告模式的,則排序是基于每行的最左邊的列的字元串的。

基于資料而非所顯示的文本來排序

有時,你想根據其它方面而非清單标簽的字元串來對清單排序。在wxPython中,你可以做到這一點,但這是較為複雜的。首先,你需要為清單中的每個項目設定項目資料,這通過使用SetItemData(item, data)方法。參數item是項目在未排序的清單中的索引,參數data必須是一個整形或長整形的值(由于C++的資料類型的限制),這就有點限制了該機制的作用。如果要擷取某行的項目資料,可以使用方法GetItemData(item)。

一旦你設定了項目資料,你就可以使用方法SortItems(func)來排序項目。參數func是一個可調用的Python對象(函數),它需要兩個整數。func函數對兩個清單項目的資料進行比較——你不能得到行自身的引用。如果第一項比第二項大的話,函數将傳回一個正整數,如果第一項比第二項小的話,傳回一個負值,如果相等則傳回0。盡管實作這個函數的最顯而易見的方法是隻對這兩個項目做一個數字的比較就可以了,但是這并不唯一的排序方法。比如,資料項可能是外部字典或清單中的一個關鍵字,與該關鍵字相應的是一個更複雜的資料項,這種情況下,你可以通過比較與該關鍵字相應的資料項來排序。

使用mixin類進行列排序

關于對一個清單控件進行排序的常見的情況是,讓使用者能夠通過在報告模式的清單的任一列上進行敲擊來根據該列進行排序。你可以使用SortItems()機制來實作,但是它在保持到列的跟蹤方面有點複雜。幸運的是,一個名為ColumnSorterMixin的wxPython的mixin類可以為你處理這些資訊,它位于wx.lib.mixins.listctrl子產品中。圖13.5顯示了使用該mixin類對列進行的排序。

聲明這個mixin就和Python中聲明任何其它的多重繼承一樣,如下所示:

import wx.lib.mixins.listctrl as listmix

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

def __init__(self, parent, log):

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

self.list = TestListCtrl(self, tID)

self.itemDataMap = musicdata

listmix.ColumnSorterMixin.__init__(self, 3)

例13.4是圖13.5的例子代碼

例13.4 使用mixin對一個報告清單進行排序

#!/usr/bin/python

#-*- encoding:UTF-8 -*-

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):

wx.Frame.__init__(self, None, -1,

"wx.ListCtrl with ColumnSorterMixin",

size=(600,400))

# load some images into an image list

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)

# add some arrows for the column sorter

# 添加箭頭到圖像清單

self.up = il.AddWithColourMask(

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

self.dn = il.AddWithColourMask(

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

# create the list control

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

# assign the image list to it

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

# Add some columns

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

self.list.InsertColumn(col, text)

# add the rows

# 建立資料映射

self.itemDataMap = {}

for item in data.rows:

index = self.list.InsertStringItem(sys.maxint, item[0])

for col, text in enumerate(item[1:]):

self.list.SetStringItem(index, col+1, text)

# give each item a data value, and map it back to the

# item values, for the column sorter

self.list.SetItemData(index, index)# 關聯資料和映射

self.itemDataMap[index] = item

# give each item a random image

img = random.randint(0, il_max)

self.list.SetItemImage(index, img, img)

# set the width of the columns in various ways

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)

# initialize the column sorter

wx.lib.mixins.listctrl.ColumnSorterMixin.__init__(self,

len(data.columns))

def GetListCtrl(self):

return self.list

def GetSortImages(self):

return (self.dn, self.up)

app = wx.PySimpleApp()

frame = DemoFrame()

frame.Show()

app.MainLoop()

為了使用該mixin工作,你需要執行下面的東西:

1、擴充自ColumnSorterMixin的類(這裡是DemoFrame)必須有一個名為GetListCtrl()的方法,它傳回實際要被排序的清單控件。該方法被這個mixin用來得到控件的一個索引。 2、在擴充自ColumnSorterMixin的類(這裡是DemoFrame)的__init__()方法中,在你調用ColumnSorterMixin的__init__()方法之前,你必須建立GetListCtrl()所要引用的清單控件。該mixin的__init__()方法要求一個代表清單控件中的列号的整數值。 3、你必須使用SetItemData()為清單中的每行設定一個唯一的資料值。 4、擴充自ColumnSorterMixin的類(這裡是DemoFrame)必須有一個名為itemDataMap的屬性。該屬性必須是一個字典。字典中的關鍵性的東西是由SetItemData()設定的資料值。這些值是你想用來對每列進行排序的值的一個元組。(典型情況下,這些值将是每列中的文本)。按句話說,itemDataMap本質上是将控件中的資料複制成另一種易于排序的形式。 在ColumnSorterMixin的通常用法中,你要麼建立itemDataMap用來添加項目到你的清單控件,要麼你首先建立itemDataMap,并用它來建造清單控件本身。 盡管配置可能有點複雜,但ColumnSorterMixin對于列的排序是一個不錯的選擇。