更改 wxGrid 中单个单元格的网格线或边框
Change grid lines or border for a single cell in a wxGrid
我试图在 wxGrid
中设置单元格,以便其中一些具有更粗或更细的边框。我想出了如何对整行或整列执行此操作(即覆盖 wxGrid::GetColGridLinePen()
和 wxGrid::GetRowGridLinePen()
),但我不知道如何更改单个单元格的边框。
我认为它应该包含一个 wxGridCellRenderer
但我似乎无法理解如何使用它。
我查看了 grid
示例,但这对我的问题没有帮助。
请问有谁能帮我指出正确的方向吗?
您确实需要使用自定义渲染器来自定义单个单元格的外观,而网格样本是正确的地方。当然,那里发生了很多事情,但是搜索 MyGridCellRenderer
以获取使用自定义渲染器的示例——这真的不难,您只需从一些现有的渲染器(例如 wxGridCellStringRenderer
对于显示文本的单元格),覆盖其 Draw()
方法,调用基本 class 方法绘制文本,然后绘制您自己的边框。
我最终创建了以下自定义网格单元格渲染器以完全控制边框的绘制方式:
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};
};
然后我禁用了网格线并将此 class 的实例传递给每个单元格,如下所示:
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));
}
}
在这个(简化的)示例中,每三列和三行会有一条较粗的黑线。这当然可以适用于任何其他类型的边框图案。
我试图在 wxGrid
中设置单元格,以便其中一些具有更粗或更细的边框。我想出了如何对整行或整列执行此操作(即覆盖 wxGrid::GetColGridLinePen()
和 wxGrid::GetRowGridLinePen()
),但我不知道如何更改单个单元格的边框。
我认为它应该包含一个 wxGridCellRenderer
但我似乎无法理解如何使用它。
我查看了 grid
示例,但这对我的问题没有帮助。
请问有谁能帮我指出正确的方向吗?
您确实需要使用自定义渲染器来自定义单个单元格的外观,而网格样本是正确的地方。当然,那里发生了很多事情,但是搜索 MyGridCellRenderer
以获取使用自定义渲染器的示例——这真的不难,您只需从一些现有的渲染器(例如 wxGridCellStringRenderer
对于显示文本的单元格),覆盖其 Draw()
方法,调用基本 class 方法绘制文本,然后绘制您自己的边框。
我最终创建了以下自定义网格单元格渲染器以完全控制边框的绘制方式:
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};
};
然后我禁用了网格线并将此 class 的实例传递给每个单元格,如下所示:
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));
}
}
在这个(简化的)示例中,每三列和三行会有一条较粗的黑线。这当然可以适用于任何其他类型的边框图案。