What's the Difference between Connect and Bind?

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
Mr-T
Experienced Solver
Experienced Solver
Posts: 58
Joined: Thu Mar 31, 2022 11:30 pm

What's the Difference between Connect and Bind?

Post by Mr-T »

As I read before, Connect can only used for wxWidgets-objects ... otherwise I have to use Bind.

Now I have the following construct:

Code: Select all

class MyNotebookContainer
{
    wxAuiNotebook* m_notebook = NULL;
    MainWindow* m_parent = NULL;

    MyNotebookContainer(MainWindow* parent)
    {
        m_parent = parent;
        m_notebook = new wxAuiNotebook(parent, wxID_ANY, ...);
        
        m_notebook->Bind(wxEVT_AUINOTEBOOK_PAGE_CLOSE, &MyNotebookContainer::OnNotebookPageClose, this);
        m_notebook->Bind(wxEVT_AUINOTEBOOK_PAGE_CHANGING, &MyNotebookContainer::OnNotebookPageChanging, this);
    }

    OnNotebookPageClose(wxAuiNotebookEvent& evt)
    {
        wxAuiNotebook* nb = (wxAuiNotebook*)evt.GetEventObject();

        if (nb != m_notebook) { evt.Veto();  return; }  // <----- run into it here!

        ....
    }

    OnNotebookPageChanging(wxAuiNotebookEvent& evt)
    {
        wxAuiNotebook* nb = (wxAuiNotebook*)evt.GetEventObject();

        if (nb != m_notebook) { evt.Veto();  return; }   // <----- run into it here!

        ....
    }

}

class MainWindow : public wxFrame
{
    wxAuiManager m_auiManager;
    MyNotebookContainer* m_container = NULL;

    MainWindow:MainWindow()
    {
        m_container = new MyNotebookContainer(this);

        m_auiManager.SetManagedWindow(this);
        m_auiManager.AddPane(m_container->m_notebook, ...);
        m_auiManager.Update();
    }
    
}
But that's not working, switching between Tabs not working (the content is not shown and the tab is not selected) but the event-handler OnNotebookPageChanging is called! And the content of the event is not correct, at least the "evt.GetEventObject()" is always another object (not the auiNotebook).

If I use Connect within the MainWindow and forward the events to the container, everything looks good.

Can someone tell me what's the difference here? In my opinion it should not matter if I use Bind or Connect.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: What's the Difference between Connect and Bind?

Post by PB »

Connect() vs Bind() should have no effect whatsoever here...

Are you sure it is really a difference between Bind() and Connect() and not just missing Skip() in the closed event handler?

EDIT You have a close, not closeD event, that should not need to be skipped, sorry for missing that. Still, I can't really explain how the way an event handler is connected can matter.

I find odd that your event handler methods do not specify the return type (which IIRC means it is an int? and void), but you probably omitted that when pasting the code.
Mr-T
Experienced Solver
Experienced Solver
Posts: 58
Joined: Thu Mar 31, 2022 11:30 pm

Re: What's the Difference between Connect and Bind?

Post by Mr-T »

Yes I'am sure. The only thing I must change was to register the Event-Handlers in the MainWindow and call the sub-handlers in my Container, that is working.

Example how it is working:

Code: Select all


class MyNotebookContainer
{
    wxAuiNotebook* m_notebook = NULL;
    MainWindow* m_parent = NULL;

    MyNotebookContainer(MainWindow* parent)
    {
        m_parent = parent;
        m_notebook = new wxAuiNotebook(parent, wxID_ANY, ...);
        
        // WARNING! that's not working! event handlers are called - but whole event-content and GUI behaviour is buggy
        //m_notebook->Bind(wxEVT_AUINOTEBOOK_PAGE_CLOSE, &MyNotebookContainer::OnNotebookPageClose, this);
        //m_notebook->Bind(wxEVT_AUINOTEBOOK_PAGE_CHANGING, &MyNotebookContainer::OnNotebookPageChanging, this);
    }

    OnNotebookPageClose(wxAuiNotebookEvent& evt)
    {
        wxAuiNotebook* nb = (wxAuiNotebook*)evt.GetEventObject();

        if (nb != m_notebook) { evt.Veto();  return; }  // <----- working now!

        ....
    }

    OnNotebookPageChanging(wxAuiNotebookEvent& evt)
    {
        wxAuiNotebook* nb = (wxAuiNotebook*)evt.GetEventObject();

        if (nb != m_notebook) { evt.Veto();  return; }   // <----- working now!

        ....
    }

}

class MainWindow : public wxFrame
{
    wxAuiManager m_auiManager;
    MyNotebookContainer* m_container = NULL;

    MainWindow:MainWindow()
    {
        m_container = new MyNotebookContainer(this);

        m_auiManager.SetManagedWindow(this);
        m_auiManager.AddPane(m_container->m_notebook, ...);
        m_auiManager.Update();
        
        Connect(m_container->m_notebook>GetId(), wxEVT_AUINOTEBOOK_PAGE_CLOSE, wxAuiNotebookEventHandler(MainWindow::OnNotebookPageClose));
        Connect(m_container->m_notebook->GetId(), wxEVT_AUINOTEBOOK_PAGE_CHANGING, wxAuiNotebookEventHandler(MainWindow::OnNotebookPageChanging));

    }
    
    OnNotebookPageClose(wxAuiNotebookEvent& evt)
    {
	    m_container->OnNotebookPageClose(evt);
    }

    OnNotebookPageChanging(wxAuiNotebookEvent& evt)
    {
	    m_container->OnNotebookPageChanging(evt);
    }    
}
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: What's the Difference between Connect and Bind?

Post by PB »

Similar but complete works just fine for me with curent(ish) master on MSW:
FWIW, I cannot reproduce with the current(ish) master on Windows with this code

Code: Select all

#include <wx/wx.h>
#include <wx/aui/auibook.h>

class Container
{
public:
    void OnPageClose(wxAuiNotebookEvent& evt)
    {
        wxAuiNotebook* notebook = dynamic_cast<wxAuiNotebook*>(evt.GetEventObject());

        wxCHECK_RET(notebook, "Invalid event object in Container::OnPageClose()");
        wxCHECK_RET(evt.GetSelection() != wxNOT_FOUND, "Invalid page index in Container::OnPageClose()");        

        if ( wxMessageBox(wxString::Format("Close page '%s'?", notebook->GetPageText(evt.GetSelection())),
                       "Container::OnPageClose()", wxYES_NO | wxYES_DEFAULT, wxGetTopLevelParent(notebook)) != wxYES)
        {
            evt.Veto();
        }
    } 
};

class MyFrame: public wxFrame
{
public:
    MyFrame() : wxFrame(nullptr, wxID_ANY, "Test")
    {
        wxAuiNotebook* notebook = new wxAuiNotebook(this);

        for ( size_t i = 0; i < 5; ++i )
        {
            wxPanel* page = new wxPanel(notebook);
                
            new wxStaticText(page, wxID_ANY, wxString::Format("StaticText on page %zu", i));
            notebook->AddPage(page, wxString::Format("Page %zu", i));         
        }            

        notebook->Bind(wxEVT_AUINOTEBOOK_PAGE_CLOSE, &Container::OnPageClose, &m_container);
    }
private:
    Container m_container;
};


class MyApp : public wxApp
{
public:
    bool OnInit() override
    {
        (new MyFrame())->Show();
        return true;
    }
}; wxIMPLEMENT_APP(MyApp);
Did you check the event you get with Bind() if it is not absolute gibberish? That could happen if your container instance for some reason had shorter lifetime and you entered the UB territory.

Either way, my guess would be you are doing something wrong in the code you did not post. That's why people are asked to post SSCEEs.
Last edited by PB on Fri May 20, 2022 12:34 pm, edited 1 time in total.
Mr-T
Experienced Solver
Experienced Solver
Posts: 58
Joined: Thu Mar 31, 2022 11:30 pm

Re: What's the Difference between Connect and Bind?

Post by Mr-T »

I'am working with Ubuntu 20.04 and GTK-3 and wx3.1.5.
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7477
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: What's the Difference between Connect and Bind?

Post by ONEEYEMAN »

Hi,
Did you try to reproduce the failure in the sample? auidemo or minimal?
Doing so will probably reveal the problem in your code as there should be no difference in those 2 functions.

Thank you.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: What's the Difference between Connect and Bind?

Post by PB »

Mr-T wrote: Fri May 20, 2022 12:33 pm I'am working with Ubuntu 20.04 and GTK-3 and wx3.1.5.
And can you reproduce the issue there with my verbatim code? AFAICT, it basically does the exact same thing you did, i.e. Bind()ing wxEVT_AUINOTEBOOK_PAGE_CLOSE to a method of a class not derived from wxEvtHandler...
Mr-T
Experienced Solver
Experienced Solver
Posts: 58
Joined: Thu Mar 31, 2022 11:30 pm

Re: What's the Difference between Connect and Bind?

Post by Mr-T »

- inherit the container from wxEvtHandler makes no difference
- build with mingw for windows contains exactly the same behavior

... I think I must generate a simple demo with that behaviour
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7477
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: What's the Difference between Connect and Bind?

Post by ONEEYEMAN »

Or reproduce it in a sample. ;-)

Thank you.
Post Reply