Introduction

This recipe is an adaptation of one of the wxPython demos currently available (as of 2004-05-12).

It shows how to arrange:

I have chopped out a lot of events machinery that was present in the original demo (merely to preserve my own sanity).

What Objects are Involved

wxListCtrl, wxListCtrlAutoWidthMixin, wxColumnSorterMixin

Process Overview

One can postpone columns definition until the list control is actually displayed. In this recipe column names are provided to the panel that hosts the list control as an attribute of the panel.

It appears to be safe to delete all of the items from a list even when the list is empty.

In this recipe the Execute method of a MySQL cursor is started to provide an iterator as a source of rows or records for populating the list using CreateRecords.

Finally PopulateList blends information about column names and from the iterator to make the list.

Special Concerns

Column names must be presented in the same order in which field values appear in rows from the iterator. Additional field values in iterator rows are ignored.

Code Sample

   1 from wxPython.wx import *
   2 from wxPython.lib.mixins.listctrl import wxColumnSorterMixin, wxListCtrlAutoWidthMixin
   3 
   4 from DisplayRecordsImages import getWhiteSquareBitmap, getSmallUpArrowBitmap, getSmallDnArrowBitmap, getXOnWhBitmap
   5 
   6 class DisplayRecordsCtrl ( wxListCtrl, wxListCtrlAutoWidthMixin ) :
   7     
   8     def __init__ ( self, parent, ID, pos = wxDefaultPosition, size = wxDefaultSize, style = 0 ) :
   9         
  10         wxListCtrl . __init__ ( self, parent, ID, pos, size = parent . GetClientSize ( ), style = style )
  11         wxListCtrlAutoWidthMixin . __init__ ( self )
  12 
  13 class DisplayRecordsCtrlPanel ( wxPanel, wxColumnSorterMixin ) :
  14     
  15     def __init__ ( self, parent, columnNames = [ ], size = ( -1, -1 ) ) :
  16         
  17         wxPanel . __init__ ( self, parent, -1, size = size )
  18 
  19         listId = wxNewId ( )
  20 
  21         self . il = wxImageList ( 16, 16 )
  22         self . idx1 = self . il . Add ( getWhiteSquareBitmap ( ) )
  23         self . sm_up = self . il . Add ( getSmallUpArrowBitmap ( ) )
  24         self . sm_dn = self . il . Add ( getSmallDnArrowBitmap ( ) )
  25         self . deleted = self . il . Add ( getXOnWhBitmap ( ) )
  26 
  27         self . list = DisplayRecordsCtrl ( self, listId, style = wxLC_REPORT | wxSUNKEN_BORDER )
  28         self . list . SetImageList ( self . il, wxIMAGE_LIST_SMALL )
  29 
  30         self . columnNames = columnNames
  31 
  32         wxColumnSorterMixin . __init__ ( self, len ( columnNames ) )
  33 
  34         EVT_SIZE ( self, self . OnSize )
  35         EVT_LIST_ITEM_SELECTED ( self, listId, self . OnItemSelected )
  36 
  37     def CreateRecords ( self, recordsIterator ) :
  38         
  39         self . itemDataMap = { }
  40         for i, row in enumerate ( recordsIterator ) : self . itemDataMap [ i ] = tuple ( row [ : len ( self . columnNames ) ] )
  41                 
  42     def PopulateList ( self ) :
  43 
  44         info = wxListItem ( )
  45         info . m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT
  46         info . m_image = -1
  47         info . m_format = 0
  48         
  49         while self . list . GetColumnCount ( ) :
  50             self . list . DeleteColumn ( 0 )
  51         
  52         for c, columnName in enumerate ( self . columnNames ) :
  53             info.m_text = columnName
  54             self . list . InsertColumnInfo ( c, info )
  55 
  56         items = self . itemDataMap . items ( )
  57         for itemNumber,  ( key, data ) in enumerate ( items ):
  58             self . list . InsertImageStringItem ( itemNumber, data [ 0 ], self . idx1 )
  59             for j in range ( 1, len ( data ) ) :
  60                 dataAsString = ''
  61                 if data [ j ] :
  62                     dataAsString = str ( data [ j ] )
  63                 self . list . SetStringItem ( itemNumber, j, dataAsString )
  64             self . list . SetItemData ( itemNumber, key )
  65 
  66         for c in range ( len ( self . columnNames ) ) :
  67             self . list . SetColumnWidth ( c, wxLIST_AUTOSIZE )
  68 
  69         self.currentItem = 0
  70 
  71     def GetListCtrl ( self ) :
  72         
  73         return self . list
  74 
  75     def GetSortImages ( self ) :
  76         
  77         return self . sm_dn, self . sm_up
  78 
  79     def OnSize ( self, event ) :
  80         w, h = self . GetClientSizeTuple ( )
  81         self . list . SetDimensions ( 0, 0, w, h )
  82         
  83     def getColumnText(self, index, col):
  84         item = self . list . GetItem ( index, col )
  85         return item . GetText ( )
  86 
  87     def OnItemSelected(self, event):
  88         self . currentItem = event . m_itemIndex
  89         event . Skip ( )
  90 
  91 if __name__ == "__main__" :
  92 
  93     import adodb
  94 
  95     db = adodb . NewADOConnection ( 'mysql' )
  96     db . Connect ( '', '', '', 'FWOTS' )
  97             
  98     def AddMenuItem ( menu, label, parent, handler, helpText = '' ) :
  99         anId = wxNewId ( )
 100         menu . Append ( anId, label, helpText ) 
 101         EVT_MENU ( parent, anId, handler )
 102         return anId
 103     
 104     class MainFrame ( wxFrame ) :
 105         
 106         def __init__ ( self, * args ) :
 107             
 108             wxFrame . __init__ ( self, * args )
 109             
 110             self . CreateStatusBar (  )
 111             self . SetStatusText ( "Click on column heading to sort" )
 112             
 113             menuBar = wxMenuBar ( )
 114             mainItem = wxMenu ( )
 115             AddMenuItem ( mainItem, "List 1", self, self . list1 )
 116             AddMenuItem ( mainItem, "List 2", self, self . list2 )
 117             menuBar . Append ( mainItem, '&File' )
 118             self . SetMenuBar ( menuBar )
 119         
 120             self . panel = DisplayRecordsCtrlPanel ( self )
 121             
 122         def list1 ( self, event = None ) :
 123 
 124             self . panel . columnNames = [ 'Company', 'City', 'Telephone 1', ] 
 125             self . panel . list . DeleteAllItems ( )
 126             rs = db . Execute ( 'select COMPANY, CITY, PHONE1, IDENTIFIER from CUSTOMERS where IDENTIFIER < 30 order by COMPANY' )
 127             self . panel . CreateRecords ( rs )
 128             self . panel . PopulateList ( )
 129             
 130         def list2 ( self, event = None ) :
 131 
 132             self . panel . columnNames = [ 'Company', 'City', ] 
 133             self . panel . list . DeleteAllItems ( )
 134             rs = db . Execute ( 'select COMPANY, CITY, PHONE1, IDENTIFIER from CUSTOMERS where IDENTIFIER < 30 order by COMPANY' )
 135             self . panel . CreateRecords ( rs )
 136             self . panel . PopulateList ( )
 137             
 138     app = wxPySimpleApp ( )
 139     frame = MainFrame ( None, wxNewId (), 'Customers List' )
 140     frame . Show ( )
 141     app . MainLoop ( )

Comments

I welcome your comments. Bill Bell

Refillable List Control (last edited 2008-03-11 10:50:30 by localhost)