wxGrid reload table

Hallo Peter,

Have a look at the wxGrid wiki at:

http://wiki.wxpython.org/index.cgi/wxGrid#head-29b445f60c263fa3715196f0d85fdd05418f02c9

Make sure to set self.currentRows and self.currentColumns in the approriate places. I actually added them to the end of ResetView and in the init for PyGridTableBase.

Hope this helps
Werner

Peter Wurmsdobler wrote:

···

Hello,

I am struggling with an apparantly simple problem: I want to change a WxGrid when the underlying data table changes.

What I did now is: I create the data table and labels, then a wxPyGridTableBase from these, and then I issue a SetTable() in what I called the Build() method of a class derived from wxGrid.

Once and a while the underlying table data change, the data table grows or shrinks in rows, and the cell data change.

I tried to recreate the wxPyGridTableBase from the new table and call SetTable again, but SetTable cannot be called twice on the same wxGrid. Do I have to destroy the entire WxGrid in this case, or is there something like ResetTable().

Any help is very much appreciated !
Thanks in advance,
peter

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwindows.org
For additional commands, e-mail: wxPython-users-help@lists.wxwindows.org

Werner,
thanks a lot for your advice. I am not quite sure whether I understand it, but the document talks about "size". This does not mean the "graphical" size of cells and the table, i.e. in pixel or so. Much of the code seems to talk rather about the graphical rescaling. I only wanted to replace the existing table in the grid with a new table, with a different row and collumn number. Or would it be better to destroy the wxGrid entirely and create it new?
peter

Peter Wurmsdobler wrote:

Werner,
thanks a lot for your advice. I am not quite sure whether I understand it, but the document talks about "size". This does not mean the "graphical" size of cells and the table, i.e. in pixel or so. Much of the code seems to talk rather about the graphical rescaling. I only wanted to replace the existing table in the grid with a new table, with a different row and collumn number. Or would it be better to destroy the wxGrid entirely and create it new?
peter

I'll assume you are using a virtual grid. In my experience, it is much easier to change the values in the table object than to replace the table itself.

I have a mixin class that helps with this:

class GridResizable:
    def __init__(self):
        self._cols = self.GetNumberCols()
        self._rows = self.GetNumberRows()
           def ResetView(self, grid):
        grid.BeginBatch()
        for current, new, delmsg, addmsg in [
            (self._rows, self.GetNumberRows(), wxGRIDTABLE_NOTIFY_ROWS_DELETED,
            wxGRIDTABLE_NOTIFY_ROWS_APPENDED),
            (self._cols, self.GetNumberCols(), wxGRIDTABLE_NOTIFY_COLS_DELETED,
            wxGRIDTABLE_NOTIFY_COLS_APPENDED),
            ]:
            if new < current:
                msg = wxGridTableMessage(self,delmsg,new,current-new)
                grid.ProcessTableMessage(msg)
            elif new > current:
                msg = wxGridTableMessage(self,addmsg,new-current)
                grid.ProcessTableMessage(msg)
        self.UpdateValues(grid)
        grid.EndBatch()
        self._rows = self.GetNumberRows()
        self._cols = self.GetNumberCols()
        # XXX
        # Okay, this is really stupid, we need to "jiggle" the size
        # to get the scrollbars to recalibrate when the underlying
        # grid changes.
        h,w = grid.GetSize()
        grid.SetSize((h+1, w))
        grid.SetSize((h, w))
        grid.ForceRefresh()

    def UpdateValues(self, grid):
        """Update all displayed values"""
        msg = wxGridTableMessage(self, wxGRIDTABLE_REQUEST_VIEW_GET_VALUES)
        grid.ProcessTableMessage(msg)

And you can use it like this:

class Table(wxPyGridTableBase, GridResizable):
        def __init__(self...):
                 GridResizable.__init__(self)

And inside your wxGrid you can now do:

self.table.changeValues(newvalues)
self.table.ResetView(self)
self.table.UpdateValues(self)

Enjoy!

···

--
Brian Kelley bkelley@wi.mit.edu
Whitehead Institute for Biomedical Research 617 258-6191

Brian,

Thanks a lot for this long and comprehensive input which I still have difficulties to comprehend.

What I want to do is simple, so I thought at least. One part of my application generates varying tables (a list of lists, i.e. a matrix sort of) and the corresponding labels, depending on a taglist :

     def BuildTable(self, taglist):
         labels = ["Tag", "Default", "Value"]
         table = []
         for tag in taglist:
             row = []
             row.append(tag)
             row.append(self.defdir[tag])
             row.append(self.valdir[tag])
             table.append(row)
         return labels, table

This method is called from a callback of a tree, or from a search machine (these produce the taglist). The caller should then do something like
         labels, table = self.BuildTable(taglist)
         self.frame.ParameterTable.Build(labels,table)

The last call in the above method is intened to update the so-called ParameterTable, with its Build method:

class CParameterTable(wxGrid):
     def __init__ (self,parent,frame):
         wxGrid.__init__(self,parent, -1)
         self.frame = frame

     def Build(self, titles, table):
         self.tabelle = CustomDataTable(titles, table)
         self.SetTable(self.tabelle)
         self.SetRowLabelSize(0)
         self.SetMargins(0,0)

by making use of wxPyGridTableBase as

class CustomDataTable(wxPyGridTableBase):
     def __init__(self, labels, table):
         wxPyGridTableBase.__init__(self)

         self.colLabels = labels
         self.table = table
         self.rows = len(self.table)
         self.cols = len(self.table[0])

So, everytime the taglist changes, the table has to be rebuilt. Certainly, the code above works only once. What would be a good and simple solution, other than recreating the entire wxGrid?

Thanks a lot for hints.
peter

Peter,

Peter Wurmsdobler wrote:

Werner,
thanks a lot for your advice. I am not quite sure whether I understand it, but the document talks about "size". This does not mean the "graphical" size of cells and the table, i.e. in pixel or so. Much of the code seems to talk rather about the graphical rescaling. I only wanted to replace the existing table in the grid with a new table, with a different row and collumn number. Or would it be better to destroy the wxGrid entirely and create it new?
peter

I am no expert here, but my small app uses a grid where I have some data which depends on a master record/row, whenever the master record/row is changed I need to update the grid with the relevant data. In my case always the same number of columns, but the number of rows change.

So, in the function where I update my table data, when I am done with it I call ResetView and it causes the grid to redraw with the new data.

See you
Werner

···

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwindows.org
For additional commands, e-mail: wxPython-users-help@lists.wxwindows.org

Werner,
Can I call you some time to get a more detailed advice. I am somehow stuck with the tabe thing. In your example, I cannot see the underlying data tabe being updated somewhere. In my imagination, I would expect a call to a grid method passing a new table. In my application some piece of code generates that table and wants the Grid to display it. Any idea?
Probably explaining on the phone would help?
peter

Peter Wurmsdobler wrote:

Werner,
Can I call you some time to get a more detailed advice. I am somehow stuck with the tabe thing. In your example, I cannot see the underlying data tabe being updated somewhere. In my imagination, I would expect a call to a grid method passing a new table. In my application some piece of code generates that table and wants the Grid to display it. Any idea?

You will have to subclass the grid to add such a beast. I whipped up an example for you. It opens up a grid with some data, and a button that, when clicked, alters the value in the grid.

The source code is commented, so you shouldn't have any trouble figuring out what is going on. I tend to use virtual grids as my workhorse since I find them much easier to manipulate than the standard grids. The biggest choice you'll make is how to describe your data. I've settled on something simple for this example:

rownames -> a list of rownames such that rowname[row] returns the rowname
colnames -> a list of column names such that colname[col] returns the colname
data[row,col] -> returns the data at row, col

row and col are integers starting at 0.

My grid has a function "grid.UpdateData(rownames, colnames, data)" which updates the displayed data in the grid. Simply call this with the new data and away you go.

Note that in a virtual table you will need to add a SetValue(self, row, col, value) in order to allow the user to change values in the data.

Good luck.

test_addingtogrid.py (4.51 KB)

···

--
Brian Kelley bkelley@wi.mit.edu
Whitehead Institute for Biomedical Research 617 258-6191