Messaging between GUI components Topic is solved

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
chadman
Experienced Solver
Experienced Solver
Posts: 70
Joined: Wed Mar 23, 2005 8:28 am

Messaging between GUI components

Post by chadman »

Hi. I have a frame with a toolbar and buttons, and then I have a panel on a splitter window elsewhere in the frame. The panel in the splitter window has controls in it. I want to make it so that when a toolbar button is clicked the value of a control in the panel in the splitter window changes.

How do I do this? Do I use the observer pattern and utilize say slots and signals? Or do I put something along the lines of the following in the function that's called when the toolbar button gets clicked:

Code: Select all

wxGetApp()->getMainFrame()->getSplitterWindow()->getControl()->setValue(value);
Or, should I use friend classes and do something like this:

Code: Select all

wxGetApp()->_mainFrame->_splitterWindow->_control->setValue(value);
Or is there yet another, possibly better way? How do all do this? What's the most common approach?
metalogic
Super wx Problem Solver
Super wx Problem Solver
Posts: 307
Joined: Fri Oct 08, 2004 8:21 am
Location: Area 51
Contact:

Post by metalogic »

Can't you just use normal wx event handling? Take a look at the connect method.
chadman
Experienced Solver
Experienced Solver
Posts: 70
Joined: Wed Mar 23, 2005 8:28 am

Post by chadman »

*THIS HAS BEEN EDITED SINCE IT WAS FIRST POSTED*
Can't you just use normal wx event handling? Take a look at the connect method.
I'm not quite sure how this would work...is something like the following what you mean?

Code: Select all

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
	: wxFrame((wxFrame*)NULL,-1,title,pos,size)
{
    dlg = new MyDialog(this, "A Dialog", 400, 300);

    dlg->Connect( wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED,
	(wxObjectEventFunction) &MyDialog::OnOK );
}
If not, can you explain it a bit more?

Also, can you use Connect() to associate an event with multiple functions?
metalogic
Super wx Problem Solver
Super wx Problem Solver
Posts: 307
Joined: Fri Oct 08, 2004 8:21 am
Location: Area 51
Contact:

Post by metalogic »

chadman wrote:I'm not quite sure how this would work...is something like the following what you mean?
Sorry, I didn't have time to elaborate when I posted earlier. Yes, that is what I meant. Although, rather than dlg->Connect(...) it should probably be myButton->Connect(...).
chadman wrote:Also, can you use Connect() to associate an event with multiple functions?
Not 100% sure but I think so.
chadman
Experienced Solver
Experienced Solver
Posts: 70
Joined: Wed Mar 23, 2005 8:28 am

Post by chadman »

Thanks, I'll give that a try then.
chadman
Experienced Solver
Experienced Solver
Posts: 70
Joined: Wed Mar 23, 2005 8:28 am

Post by chadman »

Well, it doesn't look like I can attach an event to multiple functions and this is what I would need to do. The first function that gets attached is the one that gets called, and the other(s) is ignored.

For instance, if I have a context menu for a control inside my main frame and I click an item in that menu, I may want 1) the value of a combo box inside my splitter window to change and 2) the value of another combo box in my main frame's toolbar to change as well. Now the toolbar would be part of the main frame's class, and the splitter window would be inside of the splitter window's class. So I'd need to 1) associate the context menu click event with a function call inside the splitter window's class which alters the combo box's value and 2) also associate the event with a function call inside the main frame which alters the toolbar combo box's value.

Now of course I could have a function inside the main frame (pseudo code again):

Code: Select all

void MyFrame::setComboValues(...)
{
    this->_splitterWindow->setComboValue(value);
    this->_myCombo->setValue(value);
}
But then I'd have to write wrapper functions for setting the value of each and every control (e.g. setComboValue()) - and that's annoying. There has to be a better way. I could make the classes friend classes, but that seems bad.

Does anyone know of a way to connect an event with multiple function calls? Or does any have any other solutions besides using the Connect() method, wrapper functions, or friend classes?
jb_coder
Super wx Problem Solver
Super wx Problem Solver
Posts: 267
Joined: Mon Oct 18, 2004 10:55 am

Post by jb_coder »

Is this were the wxEvent.Skip() function is used to keep the message propagating through the system?
chadman
Experienced Solver
Experienced Solver
Posts: 70
Joined: Wed Mar 23, 2005 8:28 am

Post by chadman »

Anyone have an answer or insight to my last question or jb_coder's question?
metalogic
Super wx Problem Solver
Super wx Problem Solver
Posts: 307
Joined: Fri Oct 08, 2004 8:21 am
Location: Area 51
Contact:

Post by metalogic »

chadman wrote:Anyone have an answer or insight to my last question or jb_coder's question?
Actually, jb_coder gave you the answer. He just phrased it as a question because he wasn't sure. Inside your event, add an event.Skip():

<airCode>
void MyFrame::MyEvent( SomeEvent & e )
{
e.Skip();

//Do your thing
}
</airCode>
chadman
Experienced Solver
Experienced Solver
Posts: 70
Joined: Wed Mar 23, 2005 8:28 am

Post by chadman »

Oh cool! I didn't realize that, but it works great! Why does this work?
metalogic
Super wx Problem Solver
Super wx Problem Solver
Posts: 307
Joined: Fri Oct 08, 2004 8:21 am
Location: Area 51
Contact:

Post by metalogic »

chadman wrote:Why does this work?
Because of an oddity in wx's event handling mechanism. In most (all?) GUI frameworks, events propagate by default. You have to explicitly stop the propagation. In wx, it's backwards, you have to explicitly force the propagation of events with the event.Skip() call.

Not sure why it's that way. Very unintuitive and it makes for ugly code as almost every event needs this Skip() call.
Post Reply