Introduction
This recipe is an adaptation of one of the wxPython demos currently available (as of 2004-05-12).
It shows how to arrange:
- to redefine column names (and, presumably, other attributes of columns at run-time, and
to repopulate a list from an iterator, in this case a MySQL cursor Execute.
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