Reputation: 425
I trying to set up the cells in a wxGrid
so that some of them have a thicker or thinner border. I figured out how to do it for entire rows or columns (i.e. overriding wxGrid::GetColGridLinePen()
and wxGrid::GetRowGridLinePen()
), but I cannot figure out how to change the border of just a single cell.
I think it should involve a wxGridCellRenderer
but I can't seem to wrap my head around how to use it.
I have looked at the grid
sample but that did not help me with my problem.
Could anyone nudge me in the right direction, please?
Upvotes: 0
Views: 630
Reputation: 425
I ended up creating the following custom grid cell renderer to have full control of how the borders are drawn:
class CellBorderRenderer : public wxGridCellNumberRenderer
{
public:
CellBorderRenderer(const wxPen& top=*wxBLACK_PEN, const wxPen& right=*wxBLACK_PEN,
const wxPen& bottom=*wxBLACK_PEN, const wxPen& left=*wxBLACK_PEN,
bool hideSelection=false)
: pen_({top, right, bottom, left}), hideSelection_(hideSelection)
{
}
void Draw(wxGrid &grid, wxGridCellAttr &attr, wxDC &dc, const wxRect &rect,
int row, int col, bool isSelected) override
{
attr.SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER);
wxGridCellNumberRenderer::Draw(grid, attr, dc, rect, row, col, hideSelection_ ? false : isSelected);
std::array<wxPoint, 5> points{rect.GetTopLeft(), rect.GetTopRight(),
rect.GetBottomRight(), rect.GetBottomLeft(),
rect.GetTopLeft()};
for (unsigned i = 0; i < pen_.size(); ++i)
{
dc.SetPen(pen_[i]);
dc.DrawLine(points[i], points[i+1]);
}
}
private:
std::array<wxPen, 4> pen_{*wxBLACK_PEN, *wxBLACK_PEN, *wxBLACK_PEN, *wxBLACK_PEN};
bool hideSelection_{false};
};
I then disabled the grid lines and passed an instance of this class to every single cell like so:
const auto thickBlackPen = wxPen(*wxBLACK, this->FromDIP(2));
for (int r = 0; r < mygrid->GetNumberRows(); ++r)
{
for (int c = 0; c < mygrid->GetNumberCols(); ++c)
{
wxPen topPen{*wxLIGHT_GREY_PEN}, rightPen{*wxLIGHT_GREY_PEN}, bottomPen{*wxLIGHT_GREY_PEN}, leftPen{*wxLIGHT_GREY_PEN};
bool hideSelection = false;
if (c % 3 == 0) // 3x3 subgrid boxes have thick border
{
rightPen = thickBlackPen;
}
if (r % 3 == 0) // 3x3 subgrid boxes have thick border
{
bottomPen = thickBlackPen;
}
mygrid->SetCellRenderer(r, c, new CellBorderRenderer(topPen, rightPen, bottomPen, leftPen, hideSelection));
}
}
In this (reduced) example there would be a thicker black line every three columns and rows. This could of course be adapted to any other kind of border pattern.
Upvotes: 0
Reputation: 22688
You do indeed need to use a custom renderer to customize the appearance of individual cells and the grid sample is the right place to look. There are, of course, a lot of things going on there, but search for MyGridCellRenderer
for an example of using a custom renderer -- it's really not difficult, you just derive from some existing renderer (e.g. wxGridCellStringRenderer
for the cells showing text), override its Draw()
method, call the base class method to draw the text and then draw your own border.
Upvotes: 2