wxGrid: column labels duplicated when using frozen columns AND custom label renderer

Hello wx users,

I use a grid with several frozen columns, using FreezeTo method.
I also need to use a custom column label renderer to modify some columns backgrounds/text.

If I do this, the labels of all frozen columns appear again at the start of the non-frozen part (see attached picture).

How I can prevent this to appear?
I don’t know if I can hide the labels, make their width 0, or anything else.

self.grid = MyGrid(self.sbox_grid, size=(1000, 800))
self.grid.CreateGrid(self.row_number, self.col_number)
self.grid.SetTable(self.table, takeOwnership=True)
self.grid.FreezeTo(0, self.vector_length)

The column label renderer does nothing special for the moment:

class MyReportLabelRenderer(glr.GridLabelRenderer):

    def __init__(self, bgcolor):
        self._bgcolor = bgcolor

    def Draw(self, grid, dc, rect, col):
        dc.SetBrush(wx.Brush(self._bgcolor))
        dc.SetPen(wx.TRANSPARENT_PEN)
        dc.DrawRectangle(rect)

Ok, I have the beginning of a solution, detailed below, but with this the labels do not refresh properly.

How can I ensure the labels are always visible, as for frozen labels or any grid cell?

Anyway here is the idea, within the Draw method of my custom column label renderer:

  • for the extra label I do not want, I simply pass the drawing
  • for the non-frozen ones I want to keep, I draw them shifted by the total width of frozen columns
self.grid = MyGrid(self.sbox_grid, size=(1000, 800))
self.grid.CreateGrid(self.row_number, self.col_number)
self.grid.SetTable(self.table, takeOwnership=True)
self.grid.FreezeTo(0, self.vector_length)
offset = self._freeze_x_shit()  # total width of frozen columns
[self.grid.SetColLabelRenderer(col, MyReportLabelRenderer(self.vector_length, offset)) for col in range(self.grid.GetNumberCols())]


class MyGrid(wx.grid.Grid, glr.GridWithLabelRenderersMixin):

    def __init__(self, *args, **kw):
        wx.grid.Grid.__init__(self, *args, **kw)
        glr.GridWithLabelRenderersMixin.__init__(self)


class MyReportLabelRenderer(glr.GridLabelRenderer):

    def __init__(self, vector_length, x_shift):
        self.vector_length = vector_length
        self.offset = -1 * x_shift

    def Draw(self, grid, dc, rect, col):
        if col >= self.vector_length:
            rect.Offset(self.offset, 0)
            hAlign, vAlign = grid.GetColLabelAlignment()
            text = grid.GetColLabelValue(col)
            self.DrawBorder(grid, dc, rect)
            self.DrawText(grid, dc, rect, text, hAlign, vAlign)
        else:
            # rect.SetSize((0, 0))
            pass

The drawing by itself, with the offset, seems to work properly, but only some labels are visible at a time, and when I move the horizontal scrollbar, some of them appears/disappears.
Basically, only the first one or two in the visible grid area are visible.
Hiding the window and putting it in front again does a partial redraw.
But at no time I have all labels always visible (and stable).

A ForcedRefresh() of the grid do not change anything.

Here some screenshoots of what I have done.

Horizontal scrollbar full left:

Horizontal scrollbar somewhere in the middle:

I can also have no label visible.

Is it possible that the pass in Draw method causing issues?

This problem has been addressed in the following pull request https://github.com/wxWidgets/Phoenix/pull/2436 Once this PR is merged, the correct labels should be displayed without needing to tweak the renderers.

1 Like

@jmoraleda - do you know when the version that fixes this, 4.2.2, will be available on PyPI?