Catch OnClick event on a grid ? Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
Muetdhiver
Super wx Problem Solver
Super wx Problem Solver
Posts: 323
Joined: Sun Jun 08, 2008 11:59 am
Location: Bordeaux, France

Catch OnClick event on a grid ?

Post by Muetdhiver » Sat Nov 01, 2008 9:16 pm

Hello !

I use a wxFrame with two Grids inside.
I'm on a very strange problem because the macro table to declare events does not have any identifiant to know on which grid the event is applied.

I used:

Code: Select all

BEGIN_EVENT_TABLE(CDisplayStats, wxFrame)

EVT_GRID_CELL_LEFT_CLICK( CDisplayStats::OnGridClick )
END_EVENT_TABLE()
And in CDisplayStats i declared this function:

Code: Select all

void
CDisplayStats::OnGridClick( wxGridEvent& event )
{
	long loc_ul_column 	= event.GetCol();
	long loc_ul_row 	= event.GetRow();

	event.Skip();
}
So, when i click on ONE of my two grids in the frame, the event is catched, and loc_ul_column and loc_ul_row have got the good values. But I haven't got any way to find the grid this event comes from ?

How should I do for example to retrieve the string contained in the grid cell I clicked on ?

Thanks for your help.
Regards,
Alexandre.

JimFairway
wxWorld Domination!
wxWorld Domination!
Posts: 1059
Joined: Sun Dec 30, 2007 6:40 pm
Location: Canada

Post by JimFairway » Sat Nov 01, 2008 10:14 pm

Hi Alexandre,

You have a small issue in that the grid object is generating the event, but your event handler is derived from wxFrame.
That means you won't be able to directly access member functions and variables of CDisplayStats (i.e. the compiler thinks 'this' is a CDisplayStats object, but it's really a grid object).

In any case, if that's not an issue, the following code in your event handler to get the wxGrid object should do the trick:

Code: Select all

void
CDisplayStats::OnGridClick( wxGridEvent& event )
{
        long loc_ul_column      = event.GetCol();
        long loc_ul_row         = event.GetRow();

        wxGrid *theGrid = wxDynamicCast(event.GetEventObject(), wxGrid);

        event.Skip();
}
If you need to get to the member variables of your CDisplayStats object, assuming that it is the parent of both grids, then:

Code: Select all

        wxGrid *theGrid = wxDynamicCast(event.GetEventObject(), wxGrid);
        CDisplayStats *myFrame = wxDynamicCast(wxGrid->GetParent(), CDisplayStats);
// now you can use myFrame to get to member variables of your frame.
Hope that helps,

Jim
OS: Vista SP1, wxWidgets 2.8.7.

tan
Moderator
Moderator
Posts: 1471
Joined: Tue Nov 14, 2006 7:58 am
Location: Saint-Petersburg, Russia

Re: Catch OnClick event on a grid ?

Post by tan » Sun Nov 02, 2008 7:06 am

Hi,
Muetdhiver wrote: So, when i click on ONE of my two grids in the frame, the event is catched, and loc_ul_column and loc_ul_row have got the good values. But I haven't got any way to find the grid this event comes from ?
do you save the grid pointers in the frame class? If not, do that. And in event handler you can check what grid is event source:

Code: Select all

void
CDisplayStats::OnGridClick( wxGridEvent& event )
{
    wxGrid* ptr = (wxGrid *)event.GetEventObject();
    if( ptr == m_pgrid1 )
    {
        // This is the grid one
    }
    else
    if( ptr == m_pgrid2 )
    {
        // This is the grid two
    }
    else
    {
        // Something is going wrong ...
    }
    ...
}
OS: Windows XP Pro
Compiler: MSVC++ 7.1
wxWidgets: 2.8.10

JimFairway
wxWorld Domination!
wxWorld Domination!
Posts: 1059
Joined: Sun Dec 30, 2007 6:40 pm
Location: Canada

Post by JimFairway » Sun Nov 02, 2008 11:36 am

Hi Tan,

I wasn't convinced that:

Code: Select all

    if( ptr == m_pgrid1 )
    {
        // This is the grid one
    }
is doable, in fact it may crash the program because of the use a static event table. The static event table used is derived from wxFrame, but the grid object is generating the event, and as m_pgrid1 does not exist in the grid object, bad things will happen.

My understanding is if you want to have another object class deal with an event requires use of Connect as follows:

Code: Select all

//     this code would appear inside of CDisplayStats object after the grid object is created.
	 m_pgrid1->Connect( m_pgrid1->GetId(),wxEVT_GRID_CELL_LEFT_CLICK,wxGridEventHandler(CDisplayStats::OnGridClick),NULL,this);
Let me know if my understanding is incorrect please!

Thanks,

Jim
OS: Vista SP1, wxWidgets 2.8.7.

vsp
Knows some wx things
Knows some wx things
Posts: 35
Joined: Mon Feb 21, 2005 12:52 pm

Post by vsp » Mon Nov 03, 2008 8:58 am

You can alternativley use the ID for finding which grid ctrl is fired.
void CDisplayStats::OnGridClick( wxGridEvent& event ){
wxMessageBox ( wxString::Format("%d" ,event.GetId()) );
event.Skip();
}

tan
Moderator
Moderator
Posts: 1471
Joined: Tue Nov 14, 2006 7:58 am
Location: Saint-Petersburg, Russia

Post by tan » Mon Nov 03, 2008 4:50 pm

Hi Jim,
JimFairway wrote:Hi Tan,

I wasn't convinced that:

Code: Select all

    if( ptr == m_pgrid1 )
    {
        // This is the grid one
    }
is doable, in fact it may crash the program because of the use a static event table. The static event table used is derived from wxFrame, but the grid object is generating the event, and as m_pgrid1 does not exist in the grid object, bad things will happen.

My understanding is if you want to have another object class deal with an event requires use of Connect as follows:

Code: Select all

//     this code would appear inside of CDisplayStats object after the grid object is created.
	 m_pgrid1->Connect( m_pgrid1->GetId(),wxEVT_GRID_CELL_LEFT_CLICK,wxGridEventHandler(CDisplayStats::OnGridClick),NULL,this);
Let me know if my understanding is incorrect please!
Well, you CAN handle event (at least wxCommandEvents) in any parent windows (e.g. wxFrame, wxDialog). In this case as i understand inside the frame there are two wxGrid objects. And it is quite correct to handle wxGrid event on the frame level (wxGridEvent actually is wxCommandEvent).
OS: Windows XP Pro
Compiler: MSVC++ 7.1
wxWidgets: 2.8.10

Muetdhiver
Super wx Problem Solver
Super wx Problem Solver
Posts: 323
Joined: Sun Jun 08, 2008 11:59 am
Location: Bordeaux, France

Post by Muetdhiver » Mon Nov 03, 2008 9:57 pm

Hi !
All I wanted to do is to get the value of a cell the user clicked on.
SO the solution expressed by JimFairway is the good one, that is to say using the GetEventObject function and dynamically cast the returned object.
So thanks for all your answers. VSP, the idea to switch with the grid ID is good, but i wasn't able to access a cell of the grid.
Again thanks, I put wxAwards for each one of you !

See you soon !!
Alexandre.
OS: Ubuntu 11.10
Compiler: g++ 4.6.1 (Eclipse CDT Indigo)
wxWidgets: 2.9.3

Post Reply