wxGridTableMessage trigger cell changed event in wxGrid 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
psychegr
Knows some wx things
Knows some wx things
Posts: 26
Joined: Wed Mar 05, 2014 1:19 pm

wxGridTableMessage trigger cell changed event in wxGrid

Post by psychegr »

Hi,

on one of my latest projects i have the need to change the wxGrid cell values dynamically using a wxGridTable.
So i have this code :

Code: Select all

wxGridTableMessage msg(m_table, wxGRIDTABLE_REQUEST_VIEW_GET_VALUES);
m_table->GetView()->ProcessTableMessage(msg);
which works ok but there is an issue that i am facing. I also have a handler for the GRID_CELL_CHANGED event where i repaint the background color of the cells. That one works ok when i change the value of cell by clicking on it and putting the value manually on the cell.
The issue is that this event is not triggered when the ProcessTableMessage is called.

My workaround would be to write a public function and call it after the ProcessTableMessage, but this would be really messy concerning that the grid table is updated by a function which has no relation to the pane that has the wxGrid control.

Can anyone suggest a better or a proper solution to this?
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxGridTableMessage trigger cell changed event in wxGrid

Post by doublemax »

The issue is that this event is not triggered when the ProcessTableMessage is called.
Why should it?

The cleanest solution would be to write your own wxGridCellRenderer that draws the background color dependent on the cell value instead of updating the color when the content changes. That's not as much effort as it may sound, you can just override wxGridCellRenderer::Draw and call the default renderer, but you pass through a different wxGridCellAttr depending on the background color you want.
Use the source, Luke!
psychegr
Knows some wx things
Knows some wx things
Posts: 26
Joined: Wed Mar 05, 2014 1:19 pm

Re: wxGridTableMessage trigger cell changed event in wxGrid

Post by psychegr »

That is not too much effort to implement but there is one boolean flag "gridChanged = true" that triggers a whole bunch of other functions like saving the grid data. My biggest concern is that flag which changes in the GRID_CELL_CHANGED event handler. If only there was a GRID_TABLE_CELL_CHANGED event.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxGridTableMessage trigger cell changed event in wxGrid

Post by doublemax »

but there is one boolean flag "gridChanged = true" that triggers a whole bunch of other functions like saving the grid data
Is that in the grid or the gridtable?

It's hard to tell without more details, but it sounds like you have a bad separation of model and view. The grid just displays the data and if a cell is changed through the editor, wxGridTableBase::SetValueXXX will be called, so your model will know about any changes. Isn't that all you need?
Use the source, Luke!
psychegr
Knows some wx things
Knows some wx things
Posts: 26
Joined: Wed Mar 05, 2014 1:19 pm

Re: wxGridTableMessage trigger cell changed event in wxGrid

Post by psychegr »

doublemax wrote:
but there is one boolean flag "gridChanged = true" that triggers a whole bunch of other functions like saving the grid data
Is that in the grid or the gridtable?

It's hard to tell without more details, but it sounds like you have a bad separation of model and view. The grid just displays the data and if a cell is changed through the editor, wxGridTableBase::SetValueXXX will be called, so your model will know about any changes. Isn't that all you need?
Maybe i should reimplement some of my functions. When i want to do stuff i think really simple. So here is what i have, a panel with a wxGrid, a toolbar, a linechart (using code based on wxFreeChart) and a couple other controls. When the panel is created, the grid has some preset values. Then the chart is created using the table from the grid. So when the user changes the chart by dragging the points with the mouse, i added mouse events on the chart, the grid values change also to reflect the changes from the chart. This is the reason that i use the table of the grid, to be able to refresh the values on the grid when the values on the chart change. The "gridChanged" flag changes to true in the GRID_CELL_CHANGED event when the user changes the value in the grid using a gridcelleditor. So if the "gridChanged" flag is true, the software asks the user to save the changes when he closes the panel. This is the simplest way to explain things. This is one example that the flag is used and it never happens because it never changes to true if someone changes the values using the chart. So it ends at loosing the modified values.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxGridTableMessage trigger cell changed event in wxGrid

Post by doublemax »

I see two options:

a) If you don't want to change too much to your current code, you could send a GRID_CELL_CHANGED event from the table to the grid when the model data changed.

b) You move the gridChanged flag to the table and add a public method to your derived class that returns the value.
Use the source, Luke!
psychegr
Knows some wx things
Knows some wx things
Posts: 26
Joined: Wed Mar 05, 2014 1:19 pm

Re: wxGridTableMessage trigger cell changed event in wxGrid

Post by psychegr »

doublemax wrote:I see two options:

a) If you don't want to change too much to your current code, you could send a GRID_CELL_CHANGED event from the table to the grid when the model data changed.

b) You move the gridChanged flag to the table and add a public method to your derived class that returns the value.
Well i followed your suggestion, for one more time 8), and decided to create an event on the class that modifies the table.
More specific i added :

Code: Select all

wxDECLARE_EVENT(EVT_DATASET_CHANGED, wxGridEvent);

in the class header file. Then i added :

Code: Select all

wxDEFINE_EVENT(EVT_DATASET_CHANGED, wxGridEvent);
in the class source file and then in the code that modifies the table i added this :

Code: Select all

wxCommandEvent event(EVT_DATASET_CHANGED);
wxPostEvent(m_handler, event);
This fires the event everytime the table changes.

To handle the event i had to write a public method in my class which i called

Code: Select all

void SetEventHandler(wxEvtHandler* handler) { m_handler = handler; }
Now to catch the event in my panel that has the grid i did the following :

Code: Select all

GridTableDataSet *dataset = new GridTableDataSet();
dataset->SetEventHandler(this);
Bind(EVT_DATASET_CHANGED, &mapViewPanel::onGridValueChanged, this);
After all these changes the event works as i expected.

The only drawback is that the update of the window is a bit slow. Combined the mouse move events, cell value changing and cell background cell color changing at the same time makes it a bit slow. Especially the drawing of the background color is the most slow because it calculates color based on all the cell values. Maybe i need to find another way to do the background color, like a wxGridCellRenderer that you mentioned earlier.

Regards
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxGridTableMessage trigger cell changed event in wxGrid

Post by doublemax »

That's much more complicated than what i had in mind. You already had an event handler for wxGRID_CELL_CHANGED, so i had just sent that event. And pushing a new event handler shouldn't have been necessary.

This is what i had in mind (untested though):

Inside class derived from wxGridTableBase:

Code: Select all

wxGrid *grid = GetView();   // assumes that the grid has been set with SetView() before
wxGridEvent evt(  wxGRID_CELL_CHANGED, grid, row, col );
grid->PostEvent(evt);
Use the source, Luke!
psychegr
Knows some wx things
Knows some wx things
Posts: 26
Joined: Wed Mar 05, 2014 1:19 pm

Re: wxGridTableMessage trigger cell changed event in wxGrid

Post by psychegr »

doublemax wrote:That's much more complicated than what i had in mind. You already had an event handler for wxGRID_CELL_CHANGED, so i had just sent that event. And pushing a new event handler shouldn't have been necessary.

This is what i had in mind (untested though):

Inside class derived from wxGridTableBase:

Code: Select all

wxGrid *grid = GetView();   // assumes that the grid has been set with SetView() before
wxGridEvent evt(  wxGRID_CELL_CHANGED, grid, row, col );
grid->PostEvent(evt);
Simple minds think complex. Complex minds think simpler.

I think i am one of the first! :D
I guess that i could use your method as it is simpler than what i thought. But i actually created a new event from a class that reads/writes the table. With that event class i can trigger more methods in my main panel so my event is more likely to suit on my needs. But yours is simpler and more delicate than mine and besides that it completely answers my question. So i am considering this thread as solved!

Thank you for your help and i will come back soon with another question! :P
Post Reply