[wxPython] wxPyGridTableBase and non-visible columns

In our application we have a bunch of objects that we would like to be
able to display in a grid. We are working on using the
wxPyGridTableBase class as the repository for the grid data.

Since our grid can be quite large, we didn't want to hide the columns
by setting the column width to 0. As per the wxPython docs..."wxGrid
sets up arrays to store individual row and column sizes when non-default
sizes are used. The memory requirements for this could become
prohibitive if your grid is very large. "

My question then is, is there an easy way to effectively hide a column?

Below is one of the tests I tried while looking for a solution.

[Note: the sample code used here is from Lucs Heimatseite's web page on
using wxGrid. It can be found at http://www.saffre.f2s.com/941.htm ]

class Column:
    "metadata for each column in the table"
    def __init__(self,name):
        self.name = name
        self.visible = true #added
        self.cellattr = wxGridCellAttr()
     
    def GetCellValue(self,row):
        if self.visible:
            return getattr(row,self.name)
        else:
            return None
    def SetCellValue(self,row,value):
        return setattr(row,self.name,value)

class FloatColumn(Column):
    def __init__(self,name,len,dec):
        Column.__init__(self,name)
        self.visible = false ##override parent visible
        self.cellattr.SetEditor(wxGridCellFloatEditor())
        self.cellattr.SetRenderer(wxGridCellFloatRenderer(len,dec))

##additional classes snipped

class MyDataTable(wxPyGridTableBase):
    def __init__(self, cols, rows):
        wxPyGridTableBase.__init__(self)
        self.columns = cols # data
        self.rows = rows
    ##snip extra code...

    def GetValue(self, rowIndex, colIndex):
        "required"
        ret = ''
        ## looking for a way to skip the paint of the column if
attribute if set
        if self.columns[rowIndex].visible == false:
            return ret
        else:
            try:
                row = self.rows[rowIndex]
                ret = self.columns[colIndex].GetCellValue(row)
            except IndexError:
                ret = ''
            print "GetValue(%d,%d) -> %s" % (rowIndex, colIndex, ret)
            return ret

As expected, when the grid is rendered, the column appears in the grid,
but the value is empty. What I would like is a way to hide the column
from even being displayed in the grid. I would like to still have the
column in the PyGridTableBase though so that it can be referenced
easily.

Most of the time this mechanism will be used to hide data that the user
doesn't need to see, such as the ID of an item. Eventually though, I
would like to be able to allow the users to set the visible flag
themselves as a means of configuring their preferences.

Has anyone done anything similar? or anyone have any ideas?

bmuir@eyrie.gsfc.nasa.gov wrote:

In our application we have a bunch of objects that we would like to be
able to display in a grid. We are working on using the
wxPyGridTableBase class as the repository for the grid data.

Since our grid can be quite large, we didn't want to hide the columns
by setting the column width to 0. As per the wxPython docs..."wxGrid
sets up arrays to store individual row and column sizes when non-default
sizes are used. The memory requirements for this could become
prohibitive if your grid is very large. "

My question then is, is there an easy way to effectively hide a column?

Below is one of the tests I tried while looking for a solution.

[Note: the sample code used here is from Lucs Heimatseite's web page on
using wxGrid. It can be found at http://www.saffre.f2s.com/941.htm ]

class Column:
    "metadata for each column in the table"
    def __init__(self,name):
        self.name = name
        self.visible = true #added
        self.cellattr = wxGridCellAttr()
         def GetCellValue(self,row):
        if self.visible:
            return getattr(row,self.name)
        else:
            return None
    def SetCellValue(self,row,value):
        return setattr(row,self.name,value)

class FloatColumn(Column):
    def __init__(self,name,len,dec):
        Column.__init__(self,name)
        self.visible = false ##override parent visible
        self.cellattr.SetEditor(wxGridCellFloatEditor())
        self.cellattr.SetRenderer(wxGridCellFloatRenderer(len,dec))

##additional classes snipped

class MyDataTable(wxPyGridTableBase):
    def __init__(self, cols, rows):
        wxPyGridTableBase.__init__(self)
        self.columns = cols # data
        self.rows = rows
    ##snip extra code...

    def GetValue(self, rowIndex, colIndex):
        "required"
        ret = ''
        ## looking for a way to skip the paint of the column if
attribute if set
        if self.columns[rowIndex].visible == false:
            return ret
        else:
            try:
                row = self.rows[rowIndex]
                ret = self.columns[colIndex].GetCellValue(row)
            except IndexError:
                ret = ''
            print "GetValue(%d,%d) -> %s" % (rowIndex, colIndex, ret)
            return ret

As expected, when the grid is rendered, the column appears in the grid,
but the value is empty. What I would like is a way to hide the column
from even being displayed in the grid. I would like to still have the
column in the PyGridTableBase though so that it can be referenced
easily.

Most of the time this mechanism will be used to hide data that the user
doesn't need to see, such as the ID of an item. Eventually though, I
would like to be able to allow the users to set the visible flag
themselves as a means of configuring their preferences.

Has anyone done anything similar? or anyone have any ideas?

You must remap values for colIndex to skip hidden cols and tell wxGrid when number of columns changed. There are special message for this purpose.

HTH,
Niki Spahiev

bmuir@eyrie.gsfc.nasa.gov wrote:

Since our grid can be quite large, we didn't want to hide the columns
by setting the column width to 0. As per the wxPython docs..."wxGrid
sets up arrays to store individual row and column sizes when non-default
sizes are used. The memory requirements for this could become
prohibitive if your grid is very large. "

I, too, read this part of the doc recently and I thought I'd have to
have a grid with columns all the same size. Having read your post
and the doco again, I realized that it mightn't take as much memory
as we'd think.

Say you have 500 columns and you resize one of these so it forces
wxGrid to store an array of column sizes. It should take less than
10 bytes per column to store this info, so that's only 5K for 500
columns. Not such a big overhead. (my first thought was 500 cols
by a million rows == 500M cells => more than 2GB needed -- but that's
not right)

So, we should probably experiment with wxGrid more -- it may be
perfectly possible to change a column's width without exhausting
memory.

Of course, we're both assuming that the doc is up-to-date and that
the source hasn't changed. <me>quickly downloads wx source</me>
Yup -- the doc is correct. If you SetColSize, then a couple of
arrays are created (widths and rightedge values). If you find that
wxGrid uses too much memory, I'll do some work and submit a patch
that fixes this memory-hungriness. After all -- you don't *need*
to store a big array if all you're changing is a few column widths.

Jack.

···

__________________________________________________
Do You Yahoo!?
Check out Yahoo! Shopping and Yahoo! Auctions for all of
your unique holiday gifts! Buy at http://shopping.yahoo.com
or bid at http://auctions.yahoo.com