0

I have a JPanel where i keep track of the mouse pointer position when it moves. I store that into some fields. How can I access the getter to read the fields of an already created object, within another object?

This is just an example, i'm struggling to get object communication without using static variables.

Some code:

class MainPanel extends JPanel implements MouseMotionListener {

  public int mouseX, mouseY

  public MainPanel(){
    this.addMouseMotionListener(this);
    ...
  }
  public void mouseMoved(MouseEvent e) {

    this.MouseX = e.getX();
    this.MouseY = e.getY();

  }

  public int getX(){

  return this.MouseX;
  }

  public int getY(){

  return this.MouseY;
  }
  ...
  }
}

class Something{

*** I want to, for example, print on console the XY coordinates of the -object-
 MainPanel. ****
}
  }

Thanks!

Gabriel
  • 5,453
  • 14
  • 63
  • 92

1 Answers1

3

There are several possible solutions.

Instance Scope

If you need access to MainPanel from Something scope (i.e., several methods in Something will use MainPanel and the intermediate states in MainPanel are important).

Pass your MainPanel instance to Something.

Use a constructor:

If Something can't do its job without MainPanel:

class Something {
    private final MainPanel mainPanel;
    
    public Something(MainPanel mainPanel) {
        this.mainPanel = mainPanel; 
    }

    public void myMethod() {
        System.out.printf("Mouse cordinates: %d x %d\n", mainPanel.getX(),
                mainPanel.getY());
    }
}

Initialization code:

MainPanel mainPanel = new MainPanel();
// ... put panel in frame, etc
Something something = new Something(mainPanel);

Use a setter:

If Something can do its job even without MainPanel:

class Something {
    private MainPanel mainPanel;
    
    public void setMainPanel(MainPanel mainPanel) {
        this.mainPanel = mainPanel
    }

    // my other methods
}

Initialization code:

MainPanel mainPanel = new MainPanel();
// ... put panel in frame, etc
Something something = new Something();
something.setMainPanel(mainPanel);

Method parameters

If you only need the state of MainPanel in the scope of a method (you don't want to hold a reference to MainPanel in Something) you can pass a instance of MainPanel where it's needed. This is the best strategy for independent methods. Even if several methods in Something need access to MainPanel, there is no point to store MainPanel as a field unless the methods are somehow "working together" on an instance of MainPanel:

public void myMethod(MainPanel mainPanel) {
    System.out.printf("Mouse postion: %d x %d\n", mainPanel.getX(),
            mainPanel.getY());
}

Usage example:

MainPanel mainPanel = new MainPanel();
Something something = new Something();
something.myMethod(mainPanel);

Finally, as well as thinking about variable scopes, you should think about what does your API really need in order to work. Something needs access to MainPanel or just to the mouse coordinates? If it only need the latter, have Something deal directly with x and y or introduce an intermediate object (if you can write an interface it is even better) and decouple Something from MainPanel:

class MainPanel extends JPanel implements MouseMotionListener {

  public int mouseX, mouseY;
  // everything else

  public Point getMousePosition() {
      return new Point(this.mouseX, this.mouseY);
  } 
}

And in Something:

public void myMethod(Point mousePosition) {
    System.out.printf("Mouse position: %d x %d\n", mousePosition.getX(),
            mousePosition.getY());
}

Why is it better? Something is not aware of MainPanel, it only knows about Point. You can create Points out of anything you want and send it to Something:

Usage example:

MainPanel mainPanel = MainPanel();
MyOtherComponent myOtherComponent = MyOtherComponent(); 
Something something = new Something();
something.myMethod(mainPanel.getMousePosition());
something.myMethod(myOtherComponent.myMousePositionMethod());
// or even
something.myMethod(new Point(1,1));
Anthony Accioly
  • 21,918
  • 9
  • 70
  • 118
  • I thought this. But in my real life Something class it requieres info from 3 or 4 different objects. Is it a good practice to pass the information using the constructor? – Gabriel Mar 05 '14 at 02:35
  • 1
    @GabrielA.Zorrilla, yes, it is ok. But if you dont like constructor with a lot of parameters and if you will use same objects for creating different other objects, than you'l probably need use `builder pattern` – msangel Mar 05 '14 at 02:39
  • Beat me to it. 3 or 4 is reasonable. Else use [builder pattern](http://en.wikipedia.org/wiki/Builder_pattern) ([example](http://stackoverflow.com/questions/5007355/builder-pattern-in-effective-java)). Only use setters if `Something` can do its job without the objects. Also, be ware of concurrency issues. – Anthony Accioly Mar 05 '14 at 02:43
  • Good stuff Anthony. Obrigado! – Gabriel Mar 06 '14 at 02:21
  • Glad to be of service :) De nada! (Covers Spanish and Portuguese :)). – Anthony Accioly Mar 06 '14 at 02:30