How to create a Checkbox Change event for a wxGrid cell - c++

I've created a wxGrid, populated it with data, and have created a column that contains checkboxes, and made them editable. All good so far.
co_Grid->SetReadOnly(at_RowCount, 24, false);
co_Grid->SetCellRenderer(at_RowCount, 24, new wxGridCellBoolRenderer);
co_Grid->SetCellEditor(at_RowCount, 24, new wxGridCellBoolEditor);
What I want to be able to do now is to add an event handler for the checkbox toggle event.
I've tried using the OnCellValueChanged event for the grid, but that only fires after the user leaves the cell, because before then the editor is still open (and the cell hasn't actually changed yet)
I'm pretty sure that I need to create an event handler for the wxGridCellBoolEditor but that's where I'm struggling.
I tried connecting an event in the OnEditorShown event, but that didn't go well (unhandled exception when I click on the cell to open the editor):
void cTeamGrid::OnEditorShown( wxGridEvent& ev )
{
int row = ev.GetRow(),
col = ev.GetCol();
co_Grid->GetCellEditor(row, col)->GetControl()->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
wxCommandEventHandler(cTeamGrid::OnGridCheckChange), NULL, this);
}
What am I doing wrong?

I had a similar problem myself. I bypassed it by setting the checkbox column to read-only and having the wxGrid control manually handle the click event to toggle the checkbox state (you also have to manage the double-click). This method is not the most orthodox, also because now each click on the cell, and not on the checkbox, will change the state. In my opinion, however, this can also be a desirable behaviour. In addition, this enables you to let the user change the checkbox with the keyboard (by capturing the KeyPress events).

Related

Call button click function from grandchild

I'm creating my first C++ wxWidgets application. I'm trying to create some kind of split button where the options are displayed in a grid. I have a custom button class which, when right-clicked on, opens a custom wxPopupTransientWindow that contains other buttons.
When I click on the buttons in the popup, I want to simulate a left click on the main button. I'm trying to achieve this through events, but I'm kinda confused.
void expandButton::mouseReleased(wxMouseEvent& evt)
{
if (pressed) {
pressed = false;
paintNow();
wxWindow* mBtn = this->GetGrandParent();
mBtn->SetLabel(this->GetLabel());
mBtn->Refresh();
wxCommandEvent event(wxEVT_BUTTON);
event.SetId(GetId());
event.SetEventObject(mBtn);
mBtn-> //make it process the event somehow?
wxPopupTransientWindow* popup = wxDynamicCast(this->GetParent(), wxPopupTransientWindow);
popup->Dismiss();
}
}
What is the best way to do this?
You should do mBtn->ProcessWindowEvent() which is a shorter synonym for mBtn->GetEventHandler()->ProcessEvent() already mentioned in the comments.
Note that, generally speaking, you're not supposed to create wxEVT_BUTTON events from your own code. In this particular case and with current (and all past) version(s) of wxWidgets it will work, but a cleaner, and guaranteed to also work with the future versions, solution would be define your own custom event and generate it instead.

How to catch KeyEvents when wxGrid Editor is Shown

When typing in a cell in wxGrid, the arrow keys function to go back and forward between the characters. However, depending on caret position I would like to move the cursor to the next cell when an arrow key is pressed. Currently, wxGrid is configured to capture Enter key, which makes the cursor to move downwards (to the cell below).
My question is how can I capture KeyEvent when editor is still shown.
My approach:
void Grid::OnGridCmdEditorShown( wxGridEvent& event )
{
m_IsEditorShown=true;
//Connect(wxEVT_KEY_DOWN,wxKeyEventHandler(Grid::OnKeyDown),NULL, this); //This approach did not help either
event.Skip();
}
void Grid::OnKeyDown(wxKeyEvent& event)
{
if(m_IsEditorShown) wxMessageBox("You are keying");
event.Skip();
}
When the editor is shown and say I type abc to the current cell, the MessageBox only appears when I press enter. How can catch the KeyEvents when the editor is still shown, for example, the user types a to the current cell and the MessageBox is shown.
You need to use a custom editor (probably just deriving from the standard wxGridCellTextEditor) and bind to the wxEVT_CHAR event of the editing control created in its Create().
Notice that if you want to handle the initial key press, which results in showing the editor in the first place, you need to override wxGridCellEditor::StartingKey() instead, as this key press happens before the editing control is shown.
One way that worked for me was to connect a handler to each grid editor after it had been created, by adding this to Grid constructor:
Bind(wxEVT_GRID_EDITOR_CREATED, [=](wxGridEditorCreatedEvent& event) {
event.GetControl()->Bind(wxEVT_KEY_DOWN, &Grid::OnKeyDown, this);
});
This will not handle the initial key press which results in showing the editor in the first place, but from what I understand that would not be necessary here.

how to save the particular cell value in database

I have ultrawinGrid related to infragistics.
In my Grid I have the column name with "Area" when user enters the value in a cell row after click on save button the value should save in database please provide the code whether I can implement in this event
ex:private void syncGrid_CellChange(object sender, CellEventArgs e)
{
}
The UltraGrid is bound to a list that is in memory and that list will automatically have the updates so there is no need to handle the CellChange event of the UltraGrid. In the event handler for the button you will need to add logic that will persist the list the grid is bound to to the database.
If you are using a DataTable/DataSet, TableAdapters provide this functionality. If you are using EntityFramework, call SaveChanges on your DBContext.

Save the state of QCheckBox in file, and load the state when program restarts

In my GUI application, I have some labels in my mainwindow the visibility of the labels are controlled from checkboxes in a dialog which opens when a button (setting) is pressed. Now, it all works fine, i.e. if I open the settings dialog I can check or uncheck the checkboxes; consequently the labels are also set visible or invisible.
mysettingsdialog.cpp
void mysettingsdialog::onclick(bool checked) //by AJ kpi conf
{
if(myCheckBox->isChecked()==true)
{
emit setlabelvisible();
}
else
{
emit setlabelinvisible();
}
}
mainwindow.cpp
MySettingsDialog* myset=new MySettingsDialog(this);
connect(myset,SIGNAL(setlabelvisible()),this,SLOT(enable1()));
connect(myset,SIGNAL(setlabelinvisible()),this,SLOT(disable1()));
void MainWindow::enable1()
{
ui->label->setVisible(true);
qDebug()<<"VISIBLE label";
}
void MainWindow::disable1()
{
ui->label->setVisible(false);
qDebug()<<"INVISIBLE label";
}
Now the problem is, every time my application restarts it does not retain the previous state of the checkboxes. So I was thinking to save the state of the checkbox in a variable and writing it to a file, so whenever my application starts it will read the file and set the status of check box accordingly.
My question is, how can I store the "state" of checkbox in a variable and write it to file. And again use the same to set the state of checkbox ???
I mean reading / writing values from file for QLabels and QLineEdits is easy enough but I am baffled about how to do it with checkbox.
Create a container to store the pointer of each checkbox.
Create another container to store the "state" of each checkbox. For a binary check box, you can use isChecked() to query whether or not a checkbox is checked. Otherwise you can call checkState() to return the state as enum if you use a tri-state check box (see the edit).
When loading settings, assign the state to each check box accordingly.
You may use QSettings to manage the settings and save them as an ini file.
Edit
Just mention there is an option for a tri-state check box. From the document:
QCheckBox optionally provides a third state to indicate "no change".
This is useful whenever you need to give the user the option of
neither checking nor unchecking a checkbox. If you need this third
state, enable it with setTristate(), and use checkState() to query the
current toggle state.

MFC Event Handlers

Just wondering what the difference between MFC control messages prefixed with the following is:
LVN (e.g. LVN_ITEMCHANGED)
HDN (e.g. HDN_TRACK)
NM (e.g. NM_HOVER)
Also, I am using a ListControl and trapping when the user clicks on an item using the NM_CLICK message. I also want to trap when a user selects a new item view a key e.g. up/down arrow keys. Can anyone tell me which message I should be trapping for this?
Thanks
LVN = ListView Notification
HDN = HeaDer control Notification
NM = er..um.. "Notification for Mouse" ?
For change in selection, you need to handle the LVN_ITEMCHANGED notification:
NMLISTVIEW & nm = *(NMLISTVIEW *) pnmh;
if ( (nm.uNewState ^ nm.uOldState) & LVIS_SELECTED)
{
// nm.iItem was selected or deselected
if (!m_internalUIChange)
{
// see below
}
}
The first "if" checks if the "selected" state has changed. Note that, when selecting a different item in the list, this still fires twice: once for the old item to be deselected, and once for the new item to be selected. This is necessary, however, to fetch a "complete deselect".
This notification fires very often - even when you modify the control programmatically. If your handler should react only to user events, you will need at least a flag that you set durign these operations (I use a class together with a RAII-Lock for that, so I don't forget to reset it)