【问题标题】:Change grid lines or border for a single cell in a wxGrid更改 wxGrid 中单个单元格的网格线或边框
【发布时间】:2022-01-15 00:44:54
【问题描述】:

我尝试在wxGrid 中设置单元格,以便其中一些具有更厚或更薄的边框。我想出了如何对整个行或列执行此操作(即覆盖 wxGrid::GetColGridLinePen()wxGrid::GetRowGridLinePen()),但我不知道如何更改单个单元格的边框。

我认为它应该涉及wxGridCellRenderer,但我似乎无法理解如何使用它。

我查看了grid 示例,但这对我的问题没有帮助。

请问有人能把我推到正确的方向吗?

【问题讨论】:

    标签: c++ wxwidgets


    【解决方案1】:

    您确实需要使用自定义渲染器来自定义单个单元格的外观,并且网格示例是查看的正确位置。当然,那里发生了很多事情,但是搜索 MyGridCellRenderer 以获取使用自定义渲染器的示例——这真的不难,您只需从一些现有的渲染器中派生(例如,wxGridCellStringRenderer 用于单元格显示文本),重写其Draw()方法,调用基类方法绘制文本,然后绘制自己的边框。

    【讨论】:

    • 感谢指点!这听起来很简单。当我查看示例时,o 卡在了星形单元渲染器上,不知何故这让我很困惑,以至于我没有再看下去。我会尽快尝试一下,当我弄清楚时会标记答案!
    • 再次感谢您,它有效!但是,网格线似乎是在网格单元渲染器绘制的下游某处绘制的。因此,当我想通过自定义网格单元格渲染器使某些单元格没有边框但网格线通常打开时,无论如何它们最终都会被绘制。似乎在这种情况下,您必须将自定义网格渲染器传递给所有单元格,以便其中一些绘制网格线而其中一些不绘制。
    • 是的,网格线是由网格本身绘制的,而不是由每个单元格绘制的。如果您需要抑制至少某些单元格的边框,恐怕您唯一的解决方案是使用EnableGridLines(false) 全局抑制网格线,然后从渲染器中绘制所有网格线。
    【解决方案2】:

    我最终创建了以下自定义网格单元格渲染器,以完全控制边框的绘制方式:

    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};
    };
    

    然后我禁用了网格线并将此类的一个实例传递给每个单元格,如下所示:

    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));
    
      }
    }
    

    在这个(简化的)示例中,每三列和三行会有一条较粗的黑线。这当然可以适应任何其他类型的边框模式。

    【讨论】:

      猜你喜欢
      • 2020-05-03
      • 1970-01-01
      • 2016-02-11
      • 2013-04-18
      • 1970-01-01
      • 2018-03-25
      • 2015-12-01
      • 2012-05-26
      • 1970-01-01
      相关资源
      最近更新 更多