DataModel is not shared between nodes

Anything that should be accessible by the user should preferable be stored in the DataModel.
The DataModel is part of the program and installation files, so if you do not store your data here, the data will only be stored locally, and the user will have to reconfigure this again on a new robot.

If you are a parent-node, you can read and modify your child-nodes.
Either by them being built-in nodes such as Wait, or by using the URCap Custom API on your child nodes.

How do I use the URCap Custom API?

Check out the section “URCap Program Node proprietary API” in the “program node configuration” document in the SDK.

Thank you, I’ve read the pdf, but does still have a few questions:
So basically by implementing a Custom API on the child node, it is possible to access methods from the parent node?
To implement this I have to define this interface with the lines:

interface CustomAPI {
Setting getSetting ();
void setSetting ( Setting setting );
boolean isOptionEnabled ();
void reset ();
}

What are the functions of what’s inside the interface? Can I find that in any documentation? When I declare the interface with these it says that the type Setting is unresolved, so that is my main problem right now. I’ve declared the interface right before ProgramNodeContribution();.

I’m still learning Java, so I’ll apologise if it is obvious.

i would also recommend using a singleton object to handle the datamodel object between your Contributions as @jubeira said.
Just initialize the datamodel by the parent/master node and save the datamodel object reference to the singleton object.

I found the CustomAPI solution awkward and didn’t found a reasonable sample code for this.

I thought I would just share what I found out, after I got it to work:
So you have to declare an interface the so called “CustomAPI” and in here you will have to declare what methods you want to use. What confused me was the things defined inside “interface CustomAPI { … }” in line 3-7 of the attached example. However in the case you only want to set the DataModel you’ll only need a method called something like “setChildDataModel( … );” or whatever.
When you’ve done this, you will have to implement this interface to the child node like line 13 in the attached example, and then override the “setChildDataModel( … );” with the functionality you want like the other picture I’ve uploaded, which is my method.
Now you can, with the help of the CustomAPI, access this method in the parent node with childAs.setChildDataModel(…); like it is done in the example from line 20. Here they are accessing the method childAs.setSetting( … );
I hope this is clear if anyone needs it, and i apologize if my terminology is wrong as I’m not an experienced Java programmer.


image

3 Likes

@chpor14,

Thanks a lot for sharing your gained knowledge, from working with this interface.

You may also want to check out this sample, demonstrating the custom API functionality:

1 Like

And the DataModel is shared between 2 nodes which are of the same kind?? I’m having the trouble to save a value with model.set and model.get, 2 nodes of the same kind get the same value but I need every node save its own data, how can I achieve this?? thanks for the help

Each individual node has its own DataModel.
This is not shared with any other instance.

In the Program Node Service class, the DataModel provided in the createNode() method is a separate instance for each node inserted.
The DataModel is empty, if this is a new instance of the node. If the node is copied or a program is loaded, this will give the DataModel containing previously configured values.

1 Like

Yes, that what I been reading every where but I don’t know why mi node keep doing this…

Capture

I hope this gif help me explain what it’s happening to me, I been checking the hello world example and the tutorial My First URCap, the hello world don’t make this but the URCap created in the tutorials do this too, I hope someone know the reason of this. Thanks for the reply

Have you some code samples to help demonstrate this? what you should be doing to achieve the desired effect is:

  1. make sure the code that defines the drop down box is in buildUI or a method called from buildUI.
  2. Add an ActionListener to your drop down box.
  3. in the actionPerformed method of that ActionListener, use something like ContributionProvider.get().itemSelected(Object selectedItem) to call the method itemSelected from your contribution class.
  4. In your itemSelected method in your contribution class, use model.set("selection", selectedItem)
  5. change your getTitle method to return model.get("selection", defaultSelection).
  6. Likewise, in openView() set the selected item of the drop down to be model.get("selection", delfaultSelection), this will change the drop downs selected item to what it was when you were last in the node.

This way your the title for each node depends on the selected item that you chose when you each node was selected.
Because there is only ever 1 instance of the view class, anything that depends solely on the state of different components in the view class can behave oddly (eg. the title of a node in the tree).

Hope this helps.

1 Like

Yes I checked all the steps and everything is right, here a left the code I checked

public void buildUI(JPanel panel, ContributionProvider contribution) {

  panel.add(createTextBox("Select the stage of the process."));
  panel.add(createVerticalSpace(5));
  panel.add(createComboBox(contribution));

}

My method createComboBox

Preformatted textprivate Box createComboBox(final ContributionProvider contribution) {

  Box box = Box.createHorizontalBox();
  box.setAlignmentX(Component.LEFT_ALIGNMENT);
  stages.setPreferredSize(new Dimension(150,25));
  stages.setPreferredSize(stages.getPreferredSize());
  stages.addItemListener(new ItemListener() {
  	@Override
  	public void itemStateChanged(ItemEvent e) {
  		contribution.get().setStage((String)e.getItem());
  	}
  });
  box.add(stages);
  return box;

}

Method in contribution to save the selection

public void setStage(final String stage) {

  undoReduManager.recordChanges(new UndoableChanges() {
  	@Override
  	public void executeChanges() {
  		model.set(nodeStage, stage);
  	}
  });

}

getTitle method

public String getTitle() {

  return model.get(nodeStage, "Not Stage Defined");

}

openView method

public void openView() {

  view.setComboBoxData(installation.getStages());
  view.setComboBoxSelection(model.get(nodeStage, "notDefined"));

}

Could it be a problem because of the installation node?? is the DataModel shared with the program nodes DataModel??

Is that everythiing your getTitle method does, also, what does your isDefined method do, does that set anything? If so you should avoid setting thingsin this method, in fact doing so is considered good practice.

Yes thats all my getTitle method, and neither use set in isDefined method

@Override
public boolean isDefined() {

  if(model.isSet(nodeStage)) {
  	return true;
  }
  return false;

}

I found a workaround if someone have the same problem, I used addActionListener to the JComboBox instead of addItemListener. I don’t know why the addItemListener was causing this.

1 Like

Note that the ItemListener will fire for a number of different reasons:
See ItemEvent docs: ItemEvent (Java Platform SE 7 )

Perhaps you should add the following to ensure the event only actually fires, when the user selected an item.

if(e.getStateChange == ItemEvent.SELECTED){
   // Do the magic
}
1 Like

After the robot program starts, will the URCap node’s DataModel be unified to one value?
We added several same URCap nodes as above gif and set different values ​​of each DataModel.
However, when the robot program is executed, the DataModel values ​​are unified into one.

I would like to know the solution to the above question.
please answer about my question.

@aofk159 i understand you adress a problem that has nothing to with sharing data between the nodes (which is explained above) so,
how do you trigger your data model inside the urcap entities? basically, for any UI Input all you need to do is to call model.set with every change (UI Input Button etc.) and (most importantly) call model.get with the specific key on openView(). The model Data will also be saved when you save your program. This way, it should be working with multiple urcaps of the same type