I’m trying to build a prototype application that consists of a table
of data linked to a graph, which will be displayed alongside the table
and updated as the data changes.
For the table I’m using a ListCtrl-derived object and, because I want
to be able to edit the data in-place, I’m also inheriting the
TextEditMixin class:
class EditableListCtrl(wx.ListCtrl, listmix.TextEditMixin):
def __init__(self, parent, ID=wx.ID_ANY, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=0):
wx.ListCtrl.__init__(self, parent, ID, pos, size, style)
listmix.TextEditMixin.__init__(self)
I want to keep my back-end data separate from its display, so my
wx.Frame-derived object has a data source object from which it reads
data to populate the ListCtrl.
self.list = EditableListCtrl(panel, style=wx.LC_REPORT)
self.list.InsertColumn(0, 'A', width=140)
self.list.InsertColumn(1, 'B', width=130)
for i in range(0, self.db.getNumRecords()):
item = self.db.getRecord(i)
index = self.list.InsertStringItem(sys.maxint, str(item[0]))
self.list.SetStringItem(index, 1, str(item[1]))
Since I now essentially have two copies of the data, I’d like to make
sure that the data source is updated whenever the ListCtrl is
edited by the user.
Is there a standard way to do this?
I have tried binding to the EVT_LIST_ITEM_DESELECTED event, but it
triggers before the TextEditMixin functionality changes the data in
the ListCtrl – the data retrieved from the ListCtrl by the callback
function is the old data.
There are two ways to synchronise the data.
1. Use a Virtual ListCtrl
When using a Virtual ListCtrl, you don’t have to add data manually. It
pulls data from your data source.
To make a ListCtrl virtual, initialise the ListCtrl with the
wx.LC_VIRTUALstyle flag.For the Virtual ListCtrl to pull the data, you need to override the
following functions (obviously you need to subclass ListCtrl first):
The first of these handles string data. I haven’t used the other
two. (If you’re not using them, just return
Noneand-1respectively.)You also need to call
SetItemCount(item_count)to tell the ListCtrlhow many records to retrieve.
To update the data source when the user modifies a cell, you need to
implement
SetVirtualData(self, row, col, text).See the presentation “Advanced wxPython Nuts and Bolts” by Robin Dunn for more information.
2. Use a regular ListCtrl
Subclass ListCtrl and override the function
SetStringItem(self, row,. In your new implementation, update your data source. Don’tcol, text)
forget to also call the base class
SetStringItem()though! Otherwise,the ListCtrl appearance won’t change.
Virtual ListCtrl is a bit more work, but recommended because you no longer end up with two copies of the data.
(Thanks to Mike Driscoll for pointing me in the right direction to find this information!)