I found on the web the method on how to add wxButton to wxGrid but I did't find any detailed c++ examples. I do got a python version to do so http://hansir.javaeye.com/blog/460172.
Today I implement a c++ version by translate the python version. I pasted my code here because I think the codes is not perfect, I hope you can help to improve the code. And also I find there are others who blocked by this trick.
The tricks background I think are as follows (May not be right because I am not familiar with wxWidgets):
* wxGrid use wxGridCellRender to display each cell of the grid.
So to display the button, we must overwrite the Draw function of the render. But sadly, it is hard to draw button by wxDC and rectangle/text.
* If the wxGrid cell is editable, wxGrid will call wxGridCellEditor->Create to create the cell editor. Funtunaly, we can create a real wxButton here accept and bind the button event.
What is unfuntunate is that we draw button using wxDC to display the button and use the real button to response to user act. It is hard to make the two "button" looks like a single one.
* To make the button react to the user, the cell of the button must be editable.
* By default, wxGrid need two mouse click to get the button to function (one is to select the cell, the other is passed to wxButton). We must react to the mouse click event to use single mouse click.
the header file tmGridCell.h:
Code: Select all
#include <wx/wx.h>
#include <wx/grid.h>
#include <wx/renderer.h>
#include <wx/event.h>
class wxGridCellButtonRenderer : public wxGridCellRenderer
{
public:
wxGridCellButtonRenderer(wxString label);
virtual ~wxGridCellButtonRenderer(void);
virtual void Draw(wxGrid &grid, wxGridCellAttr &attr, wxDC &dc, const wxRect &rect, int row, int col, bool isSelected);
virtual wxSize GetBestSize(wxGrid &grid, wxGridCellAttr& attr, wxDC &dc, int row, int col);
virtual wxGridCellRenderer *Clone() const;
private:
wxString m_strLabel;
};
class wxGridCellButtonEditor : public wxEvtHandler, public wxGridCellEditor
{
public:
wxGridCellButtonEditor(wxString label);
virtual ~wxGridCellButtonEditor(void);
virtual void Create(wxWindow *parent, wxWindowID id, wxEvtHandler* pEvtHandler);
void OnButton(wxCommandEvent &evt);
virtual void SetSize(const wxRect &rect);
virtual void BeginEdit(int row, int col, wxGrid *pGrid);
virtual bool EndEdit(int row, int col, wxGrid* grid);
virtual void Reset();
virtual wxString GetValue() const;
virtual wxGridCellEditor *Clone() const;
private:
wxString m_strLabel;
wxButton *m_pButton;
DECLARE_NO_COPY_CLASS(wxGridCellButtonEditor)
};
class tmGrid : public wxGrid
{
public:
tmGrid(wxWindow *parent, wxWindowID id, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize,
long style = wxWANTS_CHARS, const wxString& name = wxPanelNameStr);
virtual ~tmGrid();
void OnLeftClick(wxGridEvent &evt);
DECLARE_EVENT_TABLE()
};
Code: Select all
#include "tmGridCell.h"
wxGridCellButtonRenderer::
wxGridCellButtonRenderer(wxString label)
{
m_strLabel = label;
}
wxGridCellButtonRenderer::
~wxGridCellButtonRenderer(void)
{
}
void wxGridCellButtonRenderer::
Draw(wxGrid &grid, wxGridCellAttr &attr, wxDC &dc, const wxRect &rect, int row, int col, bool isSelected)
{
wxRendererNative::Get().DrawPushButton(&grid, dc, rect, wxCONTROL_CURRENT);
wxFont font = grid.GetFont();
dc.SetFont(font);
int x = rect.x + 10;
int y = rect.y + 1;
dc.DrawText(m_strLabel, x, y);
}
wxSize wxGridCellButtonRenderer::
GetBestSize(wxGrid &grid, wxGridCellAttr &attr, wxDC &dc, int row, int col)
{
wxString text = grid.GetCellValue(row, col);
dc.SetFont(attr.GetFont());
return dc.GetTextExtent(text);
}
wxGridCellRenderer *wxGridCellButtonRenderer::
Clone() const
{
return new wxGridCellButtonRenderer(m_strLabel);
}
////////////////////////////////////////////////////////////////////////////////////////////
wxGridCellButtonEditor::
wxGridCellButtonEditor(wxString label)
{
m_strLabel = label;
}
wxGridCellButtonEditor::
~wxGridCellButtonEditor(void)
{
}
void wxGridCellButtonEditor::
Create(wxWindow *parent, wxWindowID id, wxEvtHandler* pEvtHandler)
{
m_pButton = new wxButton(parent, id, m_strLabel);
SetControl(m_pButton);
m_pButton->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wxGridCellButtonEditor::OnButton));
}
void wxGridCellButtonEditor::
OnButton(wxCommandEvent &evt)
{
evt.Skip();
}
void wxGridCellButtonEditor::
SetSize(const wxRect &rect)
{
m_pButton->SetSize(rect.x, rect.y, rect.width+2, rect.height+2, wxSIZE_ALLOW_MINUS_ONE);
}
void wxGridCellButtonEditor::
BeginEdit(int row, int col, wxGrid *pGrid)
{
wxGridEvent evt(wxID_ANY, wxEVT_GRID_CELL_LEFT_CLICK, pGrid, row, col);
wxPostEvent(m_pButton, wxCommandEvent(wxEVT_COMMAND_BUTTON_CLICKED));
}
bool wxGridCellButtonEditor::
EndEdit(int row, int col, wxGrid* grid)
{
return true;
}
void wxGridCellButtonEditor::
Reset()
{
}
wxString wxGridCellButtonEditor::
GetValue() const
{
return wxEmptyString;
}
wxGridCellEditor *wxGridCellButtonEditor::
Clone() const
{
return new wxGridCellButtonEditor(m_strLabel);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
BEGIN_EVENT_TABLE(tmGrid, wxGrid)
EVT_GRID_CELL_LEFT_CLICK(tmGrid::OnLeftClick)
END_EVENT_TABLE()
tmGrid::
tmGrid(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style, const wxString &name)
: wxGrid(parent, id, pos, size, style, name)
{
}
tmGrid::
~tmGrid()
{
}
void tmGrid::
OnLeftClick(wxGridEvent &evt)
{
SetGridCursor(evt.GetRow(), evt.GetCol());
evt.Skip();
}