6d. wxWidgets – Event Propagation

OVERVIEW

In the previous section we saw how events are generated and handled. Most events are derived from the wxCommandEvent class. There are some events which are not derived from wxCommandEvent like wxMouseEvent or wxClose. So we have two kinds of events – basic events and command events. Command events are propagated upwards within the GUI hierarchy, by default. For eg.if a button is contained with a panel and the panel is contained within a frame, then by default the button click will be detected by the button and then by the panel and then by the frame. But this propagation happens only if you have not added an event handler of your own to deal with the event. In case you have your own event handler but still want the event to propagate upwards then you can use Event.Skip().

The sample code below has the following GUI hierarchy: frame->panel1->panel11->button. The button has an event handler for a click event. We are then propagating this event up through the hierarchy by using event.Skip(). It reaches the event handler of the top level window frame.

You can try changing the code and by removing the Skip() method in any of the event handlers and check that the event propagation stops at that point.

SAMPLE CODE

events-propagate.h
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
    #include <wx/wx.h>
#endif

class EventsPropagate: public wxFrame {

    public:
      EventsPropagate(const wxString &title);
      void OnClick(wxCommandEvent &event);
      void OnClick2(wxCommandEvent &event);
      void OnClick3(wxCommandEvent &event);
      void OnClick4(wxCommandEvent &event);
 
};

const int ID_PANEL_1 = 101;
const int ID_PANEL_1_1 = 102;
const int ID_BUTTON_1 = 200;


events-propagate.cpp
#include "events-propagate.h"


EventsPropagate::EventsPropagate(const wxString &title):

    wxFrame(NULL, -1, title, wxDefaultPosition, wxSize(500,200)) {
    wxPanel *basePanel = new wxPanel(this, -1);
    wxBoxSizer *baseSizer = new wxBoxSizer(wxVERTICAL);
    basePanel->SetSizer(baseSizer);

    wxPanel *panel1 = new wxPanel(basePanel, ID_PANEL_1);
    panel1->SetBackgroundColour(wxColour(100,200,100));
    wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
    panel1->SetSizer(vbox);

    wxPanel *panel11 = new wxPanel(panel1, ID_PANEL_1_1);
    panel11->SetBackgroundColour(wxColour(50,180,45));
    wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL);
    panel11->SetSizer(hbox);

    wxButton *btn = new wxButton(panel11, ID_BUTTON_1, wxT("Click this button"));
    hbox->Add(btn, 0, wxALIGN_CENTER);

    vbox->Add(panel11, 1, wxALL | wxEXPAND, 50);

    baseSizer->Add(panel1, 1, wxALL | wxEXPAND,5);

    btn->Bind(wxEVT_BUTTON, &EventsPropagate::OnClick, this);
    panel11->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &EventsPropagate::OnClick2, this);
    panel1->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &EventsPropagate::OnClick3, this);
    this->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &EventsPropagate::OnClick4, this);

    Center();

}

void EventsPropagate::OnClick(wxCommandEvent &event) {
	wxString msg= "Click detected in btn ";
	wxMessageBox(msg);

        event.Skip();
}

void EventsPropagate::OnClick2(wxCommandEvent &event) {
	wxString msg= "Click detected in panel11 ";
	wxMessageBox(msg);
	event.Skip();

}

void EventsPropagate::OnClick3(wxCommandEvent &event) {
	wxString msg= "Click detected in panel1";
	wxMessageBox(msg);
	event.Skip();

}

void EventsPropagate::OnClick4(wxCommandEvent &event) {
	wxString msg= "Click detected in window frame ";
	wxMessageBox(msg);
}

main.h
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
    #include <wx/wx.h>
#endif

class Main: public wxApp {

	public:
	        virtual bool OnInit();
};
main.cpp
#include "main.h"
#include "events-propagate.h"
 
IMPLEMENT_APP(Main)

bool Main::OnInit() {

    EventsPropagate *app = new EventsPropagate(wxT("Events Propagation"));
    app->Show(true);
}

The output is given below

Be the first to comment

Leave a Reply

Your email address will not be published.


*