Event class simple question

This forum can be used to talk about general design strategies, new ideas and questions in general related to wxWidgets. If you feel your questions doesn't fit anywhere, put it here.
Post Reply
guzzi_jones
Experienced Solver
Experienced Solver
Posts: 81
Joined: Sun Dec 08, 2013 3:50 am

Event class simple question

Post by guzzi_jones » Thu Jan 15, 2015 3:48 am

Is the event class essentially the callback mechinism in wxwidgets?

Ie it is the class that is inherited from by the callee to allow for callbacks?

edit*
Simply put what does the connect() function actually do ? does it somehow insert the function passed into the calling object instance?

DavidHart
Site Admin
Site Admin
Posts: 4008
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Re: Event class simple question

Post by DavidHart » Thu Jan 15, 2015 9:29 am

Hi,
Is the event class essentially the callback mechinism in wxwidgets?
Not the class itself, no.
Ie it is the class that is inherited from by the callee to allow for callbacks?
I'm not sure what you mean by that, but the answer is likely to be 'No'.
Simply put what does the connect() function actually do ? does it somehow insert the function passed into the calling object instance?
No. It tells the destination class to watch for wxEvents (or a particular subclass e.g. wxCommandEvent) with a certain event-type and ID-range, and to foward any that arrive to a particular class method. It also ensures that the first event-handler that the origin object knows about is that of the destination class. The wxEvent itself is just the message, not the mechinism.

It might help you to read the section of the event overview that talks about event-handlers; in particular item 3 and later. OTOH the event system will continue to work, whether or not you understand it ;) .

Regards,

David

guzzi_jones
Experienced Solver
Experienced Solver
Posts: 81
Joined: Sun Dec 08, 2013 3:50 am

Re: Event class simple question

Post by guzzi_jones » Thu Jan 15, 2015 2:06 pm

ok so let me break this down and maybe that will help me.
I have a frame: myframe::wxFrame

it has a button:

Code: Select all

AddButton = new wxButton(Panel1, ID_Add, _("Add"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_Add"));
here is the connect line:

Code: Select all

    Connect(ID_Add,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&myFrame::OnAddClick);
here is the event handler

Code: Select all

    void editchain::OnAddClick(wxCommandEvent& event)
    {
       dbcon * Conn;
       Conn = new dbcon;
       Conn->SetConnection();
    }
The first parm is the private variable ID_ADD of the myframe class.
The second parm is the event Type.
The third parm is the function to be called.

I am at a lose as to what the ID_ADD is for? I suspect it is somehow in play for how events BUBBLE up.

Looking at some blog posts it would seem this makes more logical sense in my head:

Code: Select all

AddButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(myFrame::buttonClick), NULL, this );
Here I am literally telling the AddButton Object Instance to listen for a wxEVT_COMMAND_BUTTON_CLICKED event and if found send processing over to the myFrame class and call .
Thanks as always.
Last edited by guzzi_jones on Thu Jan 15, 2015 3:13 pm, edited 1 time in total.

DavidHart
Site Admin
Site Admin
Posts: 4008
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Re: Event class simple question

Post by DavidHart » Thu Jan 15, 2015 3:01 pm

here is the connect line:
Connect(ID_Add,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&myFrame::OnAddClick);
It would be less ugly, and make the comparison easier, to follow the format of your second example:
Connect(ID_Add, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(myFrame::OnAddClick));
and it would be safer to add the last two parameters explicitly, rather than relying on the defaults (fine on this occasion, but a bad habit to get into):
Connect(ID_Add, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(myFrame::OnAddClick), NULL, this);

To expand it even further, what you're really doing is:
this->Connect(ID_Add, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(myFrame::OnAddClick), NULL, this);
where 'this' is an instance of myFrame.

And one more expansion: the second example is also relying on a default value (the macro expands it automatically). What it's actually doing is:
AddButton->Connect( wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(myFrame::buttonClick), NULL, this );
i.e. If the event-type is correct, connect any event; don't check the ID.

Now let's compare:
this->Connect(ID_Add,... NULL, this );
AddButton->Connect( wxID_ANY,... NULL, this );
Doing it the first way, you connect the frame to itself; the second way, the button is connected to the frame.
I am at a lose as to what the ID_ADD is for?
Again, let's compare. In the second way, any ID will be connected. Since a button always uses its own ID, that's not a problem.
However if you used wxID_ANY in the first way, any button click would be connected to OnAddClick(). That's fine if your frame has only one button, but not otherwise!
I suspect it is somehow in play for how events BUBBLE up.
That isn't, no. But bubbling up explains why method one works at all:
  • 1) The button is clicked, so it generates an event and tries to process it itself.
    2) Its default handler doesn't care about the event, so it calls the next handler in the chain. That'll be the parent, a panel.
    3) The panel receives the event, shrugs its shoulders and passes it on to its parent, the frame.
    4) The frame gets the event, says 'Aha!' and passes it to its OnAddClick() method.
This works because button-clicks produce wxCommandEvents, and these propagate to parent controls. Try the same thing with a mouse-click, and it would fail: wxMouseEvent doesn't propagate.

guzzi_jones
Experienced Solver
Experienced Solver
Posts: 81
Joined: Sun Dec 08, 2013 3:50 am

Re: Event class simple question

Post by guzzi_jones » Thu Jan 15, 2015 3:55 pm

So essentially when the CONNECT code is called with the eventSink parameter set it will create a (delegate instance,event type, id, function) to be acted upon as apposed to (just an ID, and event type and function).
via : wxEvtHandler* m_eventSink;

Code: Select all

struct WXDLLIMPEXP_BASE wxDynamicEventTableEntry : public wxEventTableEntryBase
{
    wxDynamicEventTableEntry(int evType, int winid, int idLast,
                             wxObjectEventFunction fn, wxObject *data, wxEvtHandler* eventSink)
        : wxEventTableEntryBase(winid, idLast, fn, data),
          m_eventType(evType),
          m_eventSink(eventSink)
    { }

    // not a reference here as we can't keep a reference to a temporary int
    // created to wrap the constant value typically passed to Connect() - nor
    // do we need it
    int m_eventType;

    // Pointer to object whose function is fn - so we don't assume the
    // EventFunction is always a member of the EventHandler receiving the
    // message
    wxEvtHandler* m_eventSink;

    DECLARE_NO_COPY_CLASS(wxDynamicEventTableEntry)
};

DavidHart
Site Admin
Site Admin
Posts: 4008
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Re: Event class simple question

Post by DavidHart » Thu Jan 15, 2015 4:17 pm

Not exactly. There will always be an eventSink; if you don't explicitly supply a different one, it will be the current instance. i.e.
foo->Connect(a,b,c); gives foo->Connect(a,b,c,NULL,foo);
Connect(a,b,c); gives Connect(a,b,c,NULL,this);

That's often what you want, but not always; and when you get it wrong the event arrives in the handler with the wrong 'this', which results in crashes and other undesirable behaviour. That's why I advise people always to specify the eventSink as it makes it easier to spot the reason for a crash, and harder to get it wrong in the first place.

guzzi_jones
Experienced Solver
Experienced Solver
Posts: 81
Joined: Sun Dec 08, 2013 3:50 am

Re: Event class simple question

Post by guzzi_jones » Thu Jan 15, 2015 4:30 pm

That was totally what i was missing!
I just went through a whole delegate tutorial on wibit.net and I was losing it as to how the event processing could call the method without the function AND the pointer to the class.

It is being SET by default. duh.

Thanks for the info. The cloud lifted enough that I can probably move forward with what I need to do now.

Post Reply