The wxPyGridTableBase class is the interface between the wxGrid and your application-specific data sources. Override methods in this class to determine how the grid will access your data. The table also provides information regarding the data type, empty and editable status of any given cell.
The major benefit of the indirection provided by the table class is the ability to edit huge data sets with the grid. When a grid instance is using a table object, the grid does not need to keep an internal record of each cell's value. Instead, the grid calls out the table for data values whenever a particular cell needs to be displayed and/or edited. This particular mode of interaction should be kept in mind when designing your table class. Caching values from remote and/or slow data sources may be a requirement to maintain interactivity within the grid's display routines.
You associate your wxPyGridTableBase object with your wxGrid object by calling wxGrid::SetTable(myTable) during initialization of the grid. Important note: you cannot call SetTable more than once for a given grid. If you need to change tables, you'll need to create a new wxGrid object. Also, depending on your version of wxPython, you may not be able to use the built-in GetView() method, as it will not return your Python wxGrid instance. You should consider storing a Python weak reference to the grid object in your table object (you will constantly need to access the grid object from your table class, incidentally).
Two of the primary customization points. These methods are called during grid initialization to return the number of columns and rows to display within the grid. Although the grid will not automatically resize to reflect changes in the results returned by these methods, you will likely want to always return accurate values to allow for automatic resizing functions such as shown in the wxGrid "Changing Size/Shape of Grid/Table" section.
int GetNumberRows() -- Return the number of rows to display within the grid
int GetNumberCols() -- Return the number of columns to display within the grid
Table Size/Shape Reconfiguration
These methods are called by the wxGrid class when the corresponding methods are called on the grid. If you do not implement the methods the calls will be ignored, and changes to the grid will not affect your table.
I would suggest not implementing these methods, and instead call the appropriate methods on the grid to reflect changes in your table (this is based on the idea that for the most part there is little code which knows how to interact with the grid class's methods, whereas your table's storage will likely be resized by functions in your program which did not relate to the GUI at all (particularly in database-based applications)).
void Clear() --
bool InsertRows(size_t pos = 0, size_t numRows = 1) --
bool AppendRows(size_t numRows = 1) --
bool DeleteRows(size_t pos = 0, size_t numRows = 1) --
bool InsertCols(size_t pos = 0, size_t numCols = 1) --
bool AppendCols(size_t numCols = 1) --
bool DeleteCols(size_t pos = 0, size_t numCols = 1) --
Cell Data Values and Data Types
Four more primary customization points. These methods are called to return information about the contents of particular cells within the grid. Your table class should override each of these methods.
bool IsEmptyCell(int row, int col) -- Returning a true value will result in the cell being "blank". No renderer or editor will be assigned, the table will not be asked for the corresponding value. Navigation keys will skip the cell, programmatic selection using the wxGrid::MoveCursor*Block commands will also skip the cell.
wxString GetTypeName(int row, int col) -- If the cell has a value (IsEmptyCell returns false), the grid will ask the table what type of data is stored in the cell. The data-type specifier is a simple string, and should match the strings passed to wxGrid::* RegisterDataType . See the wxGrid section "Data Types, Renderers and Editors" for more details.
wxString GetValue(int row, int col) -- Called to retrieve a text value for the default editor/render classes, the grid will call this method. Note that this is a string-only method. I would suggest creating another method GetValueAsObject(self, row, col) for use by Python code instead of this method.
void SetValue(int row, int col, const wxString& value) -- Called by the wxPyGridCellEditor classes (from their EndEdit method) to store updated values. Note: although the signature for the function specifies that the value must be a string, your Python editor code will call your Python table code directly, so arbitrary Python objects can be supported. If you prefer, consider defining a SetValueAsObject method to mirror the suggested GetValueAsObject method.
If you came here looking for something to copy/paste, the following code should get you started.
1 class MyGridTable(wx.grid.PyGridTableBase): 2 def GetNumberRows(self): 3 """Return the number of rows in the grid""" 4 return 20 5 6 def GetNumberCols(self): 7 """Return the number of columns in the grid""" 8 return 3 9 10 def IsEmptyCell(self, row, col): 11 """Return True if the cell is empty""" 12 return False 13 14 def GetTypeName(self, row, col): 15 """Return the name of the data type of the value in the cell""" 16 return None 17 18 def GetValue(self, row, col): 19 """Return the value of a cell""" 20 return "a cell" 21 22 def SetValue(self, row, col, value): 23 """Set the value of a cell""" 24 pass
wxWindows Data-type-specific Methods
These methods are called when the non-string wxPython data type renderers/editors are used. I have never used them myself, but if there is a chance you will use these renderers/editors you should define the appropriate methods. Keep in mind that the method implementations will likely be identical to your GetValue and SetValue methods for most of the data types.
bool CanGetValueAs(int row, int col, const wxString& typeName) --
bool CanSetValueAs(int row, int col, const wxString& typeName) --
long GetValueAsLong(int row, int col) --
double GetValueAsDouble(int row, int col) --
bool GetValueAsBool(int row, int col) --
void SetValueAsLong(int row, int col, long value) --
void SetValueAsDouble(int row, int col, double value) --
void SetValueAsBool(int row, int col, bool value) --
void* GetValueAsCustom(int row, int col, const wxString& typeName) --
void SetValueAsCustom(int row, int col, const wxString& typeName, void* value) --
Two more primary customization points. Overriding these methods allows you to return string labels for individual columns/rows. The default implementations return spreadsheet-like label values.
Note: As far as I am aware, there is no way to provide "owner-drawn" labels, so there is no mechanism available for including other elements, such as icons, in the label headers.
wxString GetRowLabelValue(int row) -- Retrieve the label for a particular row
wxString GetColLabelValue(int col) -- Retrieve the label for a particular column
void SetRowLabelValue(int WXUNUSED(row), const wxString&) -- Calls to the grid's SetRowLabelValue method are forwarded here, by default the change is ignored
void SetColLabelValue(int WXUNUSED(col), const wxString&) -- Calls to the grid's SetColLabelValue method are forwarded here, by default the change is ignored
You can customize these methods to allow for special processing during getting/setting the grid associated with this table. Note that, depending on your version of wxPython, the objects returned/set by these methods will not likely be your true Python object, so you will want to use an alternate method for storing a (weak) reference to your Python wxGrid instance.
void SetView(wxGrid* grid) -- Store the pointer to the grid
wxGrid * GetView() const -- Retrieve the pointer to the grid
Grid-cell Attribute Management (+Read-Only Cells)
wxGrid provides a mechanism for customising the display of particular cells using wxGridCellAttr objects. The default mode of operation for these objects creates a wxGridCellAttrProvider which stores the associated attributes for given cells, columns and rows. However, this method requires that you explicitly set the attributes for all cells in the table (basically requiring you to iterate over your (potentially huge) table finding any cells which would require a non-default attribute).
The wxPyGridTableBase allows you to intercept the request for an attribute object by overriding the GetAttr method. When you override this method, you can examine the cell value in your application's storage and decide whether to return the default attribute object (return None) or a specially configured object (a wxGridCellAttr object with various flags set).
wxGridCellAttr* GetAttr(int row, int col) -- by default forwarded to wxGridCellAttrProvider if any. May be overridden to handle attributes directly in the table.
1 ### example of attributes computed on-demand by a table 2 def GetAttr(self, row, col, someExtraParameter ): 3 """Part of a workaround to avoid use of attributes, queried by _PropertyGrid's IsCurrentCellReadOnly""" 4 property = self.GetPropertyForCoordinate( row, col ) 5 object = self.GetObjectForCoordinate( row, col ) 6 if property.ReadOnly( object ): 7 attr = wxGridCellAttr() 8 attr.SetReadOnly( 1 ) 9 return attr 10 return None
These methods all assume that you will be using an attribute storage mechanism (a wxGridCellAttrProvider). I've never done this, and don't really see it as a particularly useful approach when using a wxPyGridTableBase-based grid. XXX Anyone want to document the methods?
void SetAttrProvider(wxGridCellAttrProvider* attrProvider) -- Attribute handling give us the attr provider to use - we take ownership of the pointer
wxGridCellAttrProvider* GetAttrProvider() const -- get the currently used attr provider (may be NULL)
bool CanHaveAttributes() -- Does this table allow attributes? Default implementation creates a wxGridCellAttrProvider if necessary.
void UpdateAttrRows(size_t pos, int numRows) -- change row/col number in attribute if needed
void UpdateAttrCols(size_t pos, int numCols) --
void SetAttr(wxGridCellAttr* attr, int row, int col) -- these functions take ownership of the pointer
void SetRowAttr(wxGridCellAttr* attr, int row) --
void SetColAttr(wxGridCellAttr* attr, int col) --
Back to the wxGrid Manual