Hello Guys,
I’m working on my first URCap and I encountered a weird behavior of JCheckBox control. It changes it’s visibility (checked / not checked) on all instances of my URCap in the program at once. Only the visibility is changed without firing a event.
I created a sample project to test it and below you will find a code used to that:
View
JCheckBox checkBox = new JCheckBox();
ViewAPIProvider apiProvider;
JLabel label = new JLabel();
public WaypointTestProgramNodeView(ViewAPIProvider apiProvider) {
this.apiProvider = apiProvider;
}
@Override
public void buildUI(JPanel panel, final ContributionProvider<WaypointTestProgramNodeContribution> provider) {
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
checkBox.setText("Check box");
checkBox.setPreferredSize(new Dimension(150,30));
checkBox.setMaximumSize(checkBox.getPreferredSize());
checkBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED){
provider.get().onCheckboxStateChanges(true);
}
else {
provider.get().onCheckboxStateChanges(false);
}
}
});
panel.add(checkBox);
label.setPreferredSize(new Dimension(150,30));
label.setMaximumSize(label.getPreferredSize());
panel.add(label);
}
public void setLabel(String value) {
label.setText(value);
}
Contribution:
private Boolean getCheckbox()
{
return dataModel.get(CHECKBOX_KEY, false);
}
private void setState(Boolean state)
{
if (state)
view.setLabel("Checked");
else
view.setLabel("Not checked");
}
public void onCheckboxStateChanges(final Boolean state)
{
apiProvider.getProgramAPI().getUndoRedoManager().recordChanges(new UndoableChanges() {
@Override
public void executeChanges() {
dataModel.set(CHECKBOX_KEY, state);
setState(state);
}
});
}
As a new user I cannot add any attachments but I’m open to provide you with screen recording as well as source code of my sample program.
Could you please suggest me what I did wrongly here?
Thanks,
Michał Besler
Usually when its a visibility thing, you’re probably missing it in your openView() method in the contribution. You should be setting the state of the checkbox there based on the output of some model.get() function.
Hello Eric,
Thank you very much for your reply. Unfortunately that’s not the case here. In openView I already had setting the state.
Below it full source code of my program:
public class WaypointTestProgramNodeContribution<EllipseProgramNodeView> implements ProgramNodeContribution{
private static final String CHECKBOX_KEY = "checkbox";
private final ProgramAPIProvider apiProvider;
private final DataModel dataModel;
private final ProgramNodeFactory programNodeFactory;
private final WaypointTestProgramNodeView view;
public WaypointTestProgramNodeContribution(ProgramAPIProvider apiProvider, WaypointTestProgramNodeView view, DataModel model) {
this.apiProvider = apiProvider;
this.dataModel = model;
this.view = view;
programNodeFactory = apiProvider.getProgramAPI().getProgramModel().getProgramNodeFactory();
}
@Override
public void openView() {
setState(getCheckbox());
}
@Override
public void closeView() {
// TODO Auto-generated method stub
}
@Override
public String getTitle() {
return "WaypointTest";
}
@Override
public boolean isDefined() {
// TODO Auto-generated method stub
return true;
}
@Override
public void generateScript(ScriptWriter writer) {
}
private Boolean getCheckbox()
{
return dataModel.get(CHECKBOX_KEY, false);
}
private void setState(Boolean state)
{
if (state)
view.setLabel("Checked");
else
view.setLabel("Not checked");
}
public void onCheckboxStateChanges(final Boolean state)
{
apiProvider.getProgramAPI().getUndoRedoManager().recordChanges(new UndoableChanges() {
@Override
public void executeChanges() {
dataModel.set(CHECKBOX_KEY, state);
setState(state);
}
});
}
}
Well I see where you’re setting the JLabel, but not the state of the checkbox. You should add a “checkbox.setSelected(state)” inside the method that you’re setting the label.
1 Like
Hello Eric,
Thanks for the follow up. Indeed adding that fixed problem with my program. Thanks a lot for your help!
In case somebody had similar issues in the future I’m adding code of the corrected version of my program below:
View:
public class WaypointTestProgramNodeView implements SwingProgramNodeView<WaypointTestProgramNodeContribution> {
JCheckBox checkBox = new JCheckBox();
ViewAPIProvider apiProvider;
JLabel label = new JLabel();
public WaypointTestProgramNodeView(ViewAPIProvider apiProvider) {
this.apiProvider = apiProvider;
}
@Override
public void buildUI(JPanel panel, final ContributionProvider<WaypointTestProgramNodeContribution> provider) {
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
checkBox.setText("Check box");
checkBox.setPreferredSize(new Dimension(150,30));
checkBox.setMaximumSize(checkBox.getPreferredSize());
checkBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED){
provider.get().onCheckboxStateChanges(true);
}
else {
provider.get().onCheckboxStateChanges(false);
}
}
});
panel.add(checkBox);
label.setPreferredSize(new Dimension(150,30));
label.setMaximumSize(label.getPreferredSize());
panel.add(label);
}
public void setLabel(String value) {
label.setText(value);
}
public void setCheckbox(Boolean value) {
checkBox.setSelected(value);
}
}
Contribution:
public class WaypointTestProgramNodeContribution<EllipseProgramNodeView> implements ProgramNodeContribution{
private static final String CHECKBOX_KEY = "checkbox";
private final ProgramAPIProvider apiProvider;
private final DataModel dataModel;
private final ProgramNodeFactory programNodeFactory;
private final WaypointTestProgramNodeView view;
public WaypointTestProgramNodeContribution(ProgramAPIProvider apiProvider, WaypointTestProgramNodeView view, DataModel model) {
this.apiProvider = apiProvider;
this.dataModel = model;
this.view = view;
programNodeFactory = apiProvider.getProgramAPI().getProgramModel().getProgramNodeFactory();
}
@Override
public void openView() {
setState(getCheckbox());
}
@Override
public void closeView() {
// TODO Auto-generated method stub
}
@Override
public String getTitle() {
return "WaypointTest";
}
@Override
public boolean isDefined() {
// TODO Auto-generated method stub
return true;
}
@Override
public void generateScript(ScriptWriter writer) {
}
private Boolean getCheckbox()
{
return dataModel.get(CHECKBOX_KEY, false);
}
private void setState(Boolean state)
{
if (state)
{
view.setLabel("Checked");
view.setCheckbox(true);
}
else
{
view.setLabel("Not checked");
view.setCheckbox(false);
}
}
public void onCheckboxStateChanges(final Boolean state)
{
apiProvider.getProgramAPI().getUndoRedoManager().recordChanges(new UndoableChanges() {
@Override
public void executeChanges() {
dataModel.set(CHECKBOX_KEY, state);
setState(state);
}
});
}
}
this concept tripped us up in the beginning of learning urcap dev, too!
There is only ever ONE single view instance of a program node, regardless of how many instances of the program node there are in the program.
…so… you need to:
- store the state/value in the model of that program node instance
- update the visuals in openView by referencing the stored model value