caRameL
caRameL

Reputation: 633

Best way to modify an object following an action in a different one

I wonder what's the best way to modify an object following an action in a different one.

Example : I have a JPanel with some components, one of it opens a new JPanel. In this new JPanel, i have a button that i would it to modify the first JPanel.

I found out 2 working solutions, and i wonder which of both is the best (or another one).

First one by adding an Actionlistener in the first class:

public class SomePanel extends JPanel{

    private JButton button = new JButton("Open New Frame");
    private SomeOtherPanel otherPanel = new SomeOtherPanel();
    private int value = 0;

    public SomePanel(){            
        // initialization code            
        button.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e) {
                otherPanel.setVisible(true);
            }                
        });

        otherPanel.getButton().addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e) {
                value = 1;
            }                
        });            
    }


public class SomeOtherPanel extends JPanel{

private JButton button = new JButton("Modify First Panel value");

    public SomeOtherPanel(){

    }
    public JButton getButton() {
        return button;
    }        
}

Second one by passing the first JPanel as parameter of the second one:

public class SomePanel extends JPanel{

    private JButton button = new JButton("Open New Frame");
    private SomeOtherPanel otherPanel = new SomeOtherPanel(this);
    private int value = 0;

    public SomePanel(){            
        // initialization code ... size, color ...            
        button.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e) {
                otherPanel.setVisible(true);
            }                
        });             
    }

    public void setValue(int value) {
        this.value = value;
    }   
}

public class SomeOtherPanel extends JPanel{

    private JButton button = new JButton("Modify First Panel value");
    public SomePanel somePanel;

    public SomeOtherPanel(SomePanel panel){
        this.somePanel = panel;
        button.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e) {
                somePanel.setValue(1);
            }                
        });
    }

    public JButton getButton() {
        return button;
    } 
}

Is this right ?

Upvotes: 1

Views: 176

Answers (2)

nachokk
nachokk

Reputation: 14413

Besides your solution is not incorrect generate high coupling between those objects so i will give you another solution.

You can take approach of the observer pattern then you decouple the visual components , the actionListener works as a controller/"mediator".

I don't know what your value do, but i put as an observable property and register an observer on it.

public class SomePanel extends JPanel{

private JButton button = new JButton("Open New Frame");
private int value;


public SomePanel(){

    // initialization code ... size, color ...

    button.addActionListener(new ActionListener(){

        @Override
        public void actionPerformed(ActionEvent e) {
              setValue(1);
        }

    });    
}

public void setValue(int value) {
    int oldValue= this.value;
    this.value = value;
    firePropertyChangeValue("value",oldValue,this.value);
}

}

In some other panel

public class SomeOtherPanel extends JPanel {

     private PropertyChangeListener listener = new ValueListener();

      public PropertyChangeListener getListener(){
                  return listener;
      }

     private class ValueListener implements PropertyChangeListener{
            @Override
            public void propertyChange(PropertyChangeEvent evt){
                        if(evt == null)
                            return;

               if(evt.getPropertyName().equals("value") && ((int) evt.getNewValue()) == 1 ){
                    SomeOtherPanel.this.setVisible(true);
               }        
            }        
     }        
 }

And in client code where you init both panels.

Example:

  JPanel panel = new SomePanel();
  SomeOtherPanel otherPanel = new SomeOtherPanel();
  panel.addPropertyChangeListener("value",otherPanel.getListener());

UPDATE

As i didn't understood what you want to achieve your solution could be easily, just simple don't use anonymous classes

public class SomePanel extends JPanel{

private ActionListener myAction = new ActionListener(){
       @Override
       public void actionPerformed(ActionEvent evt){
           value =1;//or what you want
       }

}; 

public ActionListener getMyAction{
    return myAction;
}


}

And in the other panel..

public class SomeOtherPanel extends JPanel {

private JButton button = new JButton();

public void addButtonAction(ActionListener listener){
   button.addActionListener(listener);
}

}

And in client code:

 JPanel panel = new SomePanel();
  SomeOtherPanel otherPanel = new SomeOtherPanel();
  otherPanel .addButtonAction(panel .getMyAction());

Upvotes: 2

SegFault
SegFault

Reputation: 1094

Both methods are ok. If you look for the cleanest way to do it, i would say it depends.

It is a cohesion problem. You must ask yourself, what is the purpose of each class.

If you think that SomeOtherPanel purpose is only to apply a change, whatever the change is, to SomePanel when pushing a button so the first method is the good one because without touching any code in SomeOtherPanel, you can choose what effect that class will have on SomePanel.

If you think that SomeOtherPanel purpose is to set to 1 the instance variable Value, then the second solution is the good one.

Upvotes: 0

Related Questions