How do I call a function of a parent component from a child component


#1

Hey I’m looking for some guidance on how to solve this issue I’m having.

I have a right click menu and inside the menu I need to call functions from other parts of the application. How would I link my components together so I can call a function that is defined outside of the component where I am creating a PopupMenu?

Lets say I have components A > B > C. I can call functions within B because C is ‘owned’ by B, but how would I pass functions that are defined in A all the way into C?


#2

Can you give a concrete example of what type of functions C wants to call in A? ie. the answer is easier to form if we understand the actual issue you are trying to solve. :slight_smile:


#3

This is a very basic question about OO principles. Since it is asked very often, I’ll try to give a bit of an overview and some advice:

  • Ideally a class should need as little knowledge of other classes as possible. The mentioned case, when class A owns B it is trivial, since B as member is known while compiling, and you can call all methods of B

  • try to think in entities: maybe B is a panel with sub-panels. in that case, A really shouldn’t know about all sub-panels. Same holds true the other way round: the sub panel shouldn’t need to know anything of the container three levels up

  • you can show and hide complete Components with all subcomponents just by b.setVisible (false); - try to use the hierarchy as much as possible. Same is possible using containers like TabbedComponent.

  • try to use the most generic interface, e.g. for layout it is sufficient to know, it’s Components, you don’t need to know, what specific Component, like TextButton etc.

  • often it helps already to add an udate() function, that just sets things accordingly. In your case A might call b.update(), which in turn calls all members c.update()…

  • if you need some kind of remote control independent of the ownership hierarchy, you can use the ChangeBroadcaster / ChangeListener interface to trigger an update

Hope there are some inspirations in that list…


#4

Alright I’ll try and explain this.

I have a set of listboxes and functions that let you move items between the different groups.

A “Group” listbox changes the view of items that are shown in a TableListBox. then if you click on an item in that Table , you can move it to another listbox(ActiveListBox)

the TableListBox and ActiveListBox are both hosted in the Group Listbox class.

I am using pointers to the XmlElements and I pass those into the two ListBoxModels and run numRows = getNumChildElements() on those pointers to get them to draw the ListBox.

there is a pointer to the XML document that is used to host all the data, since I am basing my app off of the tableListBoxModel tutorial this is still:

std::unique_ptr tutorialData;

rather then passing that pointer into the listbox model and executing things like writeToXml(); within each listboxmodel i thought I would set it up so the tables ONLY display data that is passed into them, and the writing and moving around of the data would occur in the class that is hosting both of those listboxes. This works fine when I use buttons to activate all the functions because I can just host those buttons within the hosting class for everything. the problem is that I would like to use right click menus and they can only access functions within the class they are owned by.

so I’ve created functions within that class that calls functions outside the class and they seem to work for basic things like an Alert Window but when I pass in any of the pointers to any of the XMLobjects or try to call a function in any of the child classes it crashes.

Ive set up a basic example to show what is causing a crash (psuedo code) :

   Class A:
 void calledFunction()
    {
  classB.insideFunctionCall();
    }

Class B:
void functionCall()
{
owner->calledFunction();
}

void insideFunctionCall() 
{
deleteSelectedElements();
}

// function to delete selected items (works)
void deleteSelectedElements();

Class C:

//right click menu if result is one
    owner.deleteSelectedElements();

//right click menu if result is 2 do this
     owner.functionCall();

that is the basic structure of what I am trying to accomplish, though if I select option 1 in the right click menu it works, but when I select option 2 it doesn’t work.


#5

another thing:

I have Listboxes B and C hosted in Listbox A, because listbox A loads the data from XML and I am going to put all file saving/loading functions within A.

I just need to create functions to get what items are selected within either ListBox B or C and then that info should be passed to A so I can use that information to make the relevant changes to the XML elements, and then those changes will be refreshed in the tables by calling the updateContent() and repaint() functions on the tables.

so If I have a button on A, that access the “setter/getter” functions in B and C, it works, but when I have a right click menu within those B and C classes, that basically say, execute the same functions as the Buttons in A, it doesn’t work. so i guess what I am asking is how I would get my right click menus to call functions in A correctly.


#6

Maybe the ValueTree class might help with what you’re trying to do here.


#7

As TaiDye indicates, maybe you should consider the problem from a data model perspective, which the simply GUI reflects. So, instead of having your GUI components talk to each other, have them update data in the underlying data, which gets reflected up through the UI in the appropriate places. ValueTree’s are an excellent tool for this.


#8

Alright thanks, it’s already working mostly with a simple XML file, so id rather just have my program read strictly from the XML file. i’ve set it up so every GUI element makes a change to the XML file and everything that is displayed is just a reflection of what is in the XML table. the listboxes and table are just passed a single pointer to one of the XML elements and will just display its child elements

the main issue is that this is my first project so I’m trying to work with minimal changes to library things, if I could just pass the pointer to the XML document then I could have my nested classes just write the changes needed, but since its the std::uniquepointer kind of pointer i figured I just wouldn’t mess with passing that around, and I couldn’t find a way to get that to compile so I decided it was a safer bet just to have all the file editing take place in the top component.

Ive been thinking about it and I think the best solution might be to go with listeners/broadcasters. my functions work already with buttons in on the top component, so all i need to do is make my right click menus send a flag like “This was clicked!” and then it can run the same function that I have assigned to the buttons. Can anyone offer some input on how to do that?


#9

thanks, I think the listeners/broadcasters idea is the way to go.