Problem with events when using GCC 6.2.0 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
Tapsa
Earned some good credits
Earned some good credits
Posts: 147
Joined: Tue Dec 06, 2011 5:52 pm
Location: Helsinki

Problem with events when using GCC 6.2.0

Post by Tapsa » Mon Nov 07, 2016 7:28 am

I recently upgraded my compiler to GCC 6.2.0 which defaults to C++14.
Changing no code at all, after a recompilation of all libs and my sources these calls no longer work:

Code: Select all

void AGE_Frame::OnUpdateCombo_Techs(wxCommandEvent &event)
{
    wxMessageBox("AGE_Frame::OnUpdateCombo_Techs");
    ((AGELinkedBox*)event.GetEventObject())->OnChoose(event); // <-- Fully ignored!
    ListEffects();
}
I can see the above message "AGE_Frame::OnUpdateCombo_Techs", but cannot see the below one:

Code: Select all

void ComboBox_Plus1::OnChoose(wxCommandEvent&)
{
    wxMessageBox("ComboBox_Plus1::OnChoose");
    TextBox->ChangeValue(lexical_cast<string>(GetSelection() - 1));
    TextBox->SaveEdits();
}
Now you might ask "maybe your code in ComboBox_Plus1 is broken?", but it works when I don't bind the wxEVT_COMMAND_COMBOBOX_SELECTED second time (in order to call ListEffects). Not all combo boxes need to refresh a list, so those that are not bound again to get a list refreshed (or some other special code), work fine and I can see the "ComboBox_Plus1::OnChoose" message.

This here is my custom combo box and the pure virtual class from where it derives.

Code: Select all

class ComboBox_Plus1: public AGEComboBox, public AGELinkedBox
{
public:
    ComboBox_Plus1(wxWindow *parent, AGETextCtrl *ptr, wxArrayString *choices, int width = AGETextCtrl::LARGE):
    AGEComboBox(parent, choices, width, 0)
    {
        TextBox = ptr;
        TextBox->LinkedBoxes.push_back(this);
        Bind(wxEVT_COMMAND_COMBOBOX_SELECTED, &ComboBox_Plus1::OnChoose, this);
    }

private:
    void OnChoose(wxCommandEvent&);
    void SetChoice(int);
    void EnableCtrl(bool yes) {Enable(yes);}
};

Code: Select all

class AGETextCtrl;
class AGELinkedBox
{
public:
    virtual void OnChoose(wxCommandEvent&)=0;
    virtual void SetChoice(int)=0;
    virtual void EnableCtrl(bool)=0;

    AGETextCtrl *TextBox;
};
In short, it is no longer possible to call void OnChoose(wxCommandEvent&) in an outside event handler function.
Is wxWidgets incompatible with C++14 yet, or am I doing something wrong?

catalin
Moderator
Moderator
Posts: 1598
Joined: Wed Nov 12, 2008 7:23 am
Location: Romania

Re: Problem with events when using GCC 6.2.0

Post by catalin » Mon Nov 07, 2016 12:15 pm

This is definitely not about GCC 6.2.0 and C++14. There is no compiled code that can be "ignored" in C++, is there ? Just step through your code with the debugger and see what goes wrong, which virtual function is picked up.
For your cast there (which BTW, is almost never needed with a good design), you should use C++ static_cast<>, which will make sure you cast to a related type in the inheritance hierarchy.

But more important, event handlers should not be virtual functions. You really need to fix that by binding all event handlers in the correct order and then using event.Skip() where appropriate. See Event Handlers vs Virtual Methods for more info.

Tapsa
Earned some good credits
Earned some good credits
Posts: 147
Joined: Tue Dec 06, 2011 5:52 pm
Location: Helsinki

Re: Problem with events when using GCC 6.2.0

Post by Tapsa » Mon Nov 07, 2016 2:54 pm

After changing all of my GetEventObject casts into static casts, I can't compile anymore.
error: invalid static_cast from type 'wxObject*' to type 'AGELinkedBox*'
AGELinkedBox is not related to wxObject.
Why this worked with earlier compiler is probably an unintended side effect.
All objects that are tried to cast do inherit from AGELinkedBox, but wxCommandEvent strips them into wxObjects :(

My actual event handlers are not virtual functions (but they override one). I have both combo and check boxes in groups that need to process similar thing (set selection, set checked). So I made my combo and check boxes inherit from a single class through which I want to call the appropriate set function, not caring if they are combo or check boxes.

Isn't event skip only required on focus event handlers?
Should skip only be called last in an event handler block? I have a bunch of returns in the middle of my handlers...

catalin
Moderator
Moderator
Posts: 1598
Joined: Wed Nov 12, 2008 7:23 am
Location: Romania

Re: Problem with events when using GCC 6.2.0

Post by catalin » Mon Nov 07, 2016 4:02 pm

Tapsa wrote:After changing all of my GetEventObject casts into static casts, I can't compile anymore.
Good, and that's a sign that you are casting [to] the wrong object.
Tapsa wrote:AGELinkedBox is not related to wxObject.
Well, then you should not cast a wxObject to it, should you ?
Whatever event.GetEventObject() returns is a wxObject - the actual wxComboBox that emitted the event. Thus, IIUC, you can at most cast it to AGEComboBox, which does not contain the code of AGELinkedBox.
Tapsa wrote:All objects that are tried to cast do inherit from AGELinkedBox
You have multiple inheritance, and wxObject is in a different branch... C++ will explain this better than I could.
Tapsa wrote:My actual event handlers are not virtual functions (but they override one).
Actually a function in a derived class overriding a virtual function is also a virtual function, whether you call it 'virtual' or not (C++).
Tapsa wrote:I have both combo and check boxes in groups that need to process similar thing (set selection, set checked). So I made my combo and check boxes inherit from a single class through which I want to call the appropriate set function, not caring if they are combo or check boxes.
I can't really follow you there, but from my understanding you just can't make it work like this... (It should probably work if you make AGELinkedBox a template class so you could derive it from either AGEComboBox or your other one (AGECheckBox ?), but I'd advise you to read a bit more about C++ before attempting that).

You are handling the events in AGE_Frame::OnUpdateCombo_Techs(). Why don't you add the common functionality in the same class? And from the event handler call it something like DoChooseForCombo(static_cast<ComboBox_Plus1>(event.GetEventObject()));
Tapsa wrote:Isn't event skip only required on focus event handlers?
No. It has nothing to do with focus event handlers in particular, but with the event processing in general. Read the event processing docs, see the samples, they should answer your other question too.

Tapsa
Earned some good credits
Earned some good credits
Posts: 147
Joined: Tue Dec 06, 2011 5:52 pm
Location: Helsinki

Re: Problem with events when using GCC 6.2.0

Post by Tapsa » Mon Nov 07, 2016 4:29 pm

I finally fixed it by casting to AGEComboBox and AGECheckBox instead of their common ancestor... thanks to suggesting me static cast.

Post Reply