views:

2970

answers:

3

Basically what I want to do is get a start button to initiate a method running in another class and acting on another object.

My code for the listener:

     button1a.addActionListener(new ActionListener() {

  public void actionPerformed (ActionEvent event) {

   // Figure out how to make this work
   //sim.runCastleCrash(); 

   }
  } );

My code for the other class:

public static void main(String[] args) {
 CastleCrash sim;
 sim = new CastleCrash();

}

.

public void runCastleCrash() {

 System.out.println("Castle Crash is beginning...");
 //Other method parts here to be added
}

I get the feeling this can't be too hard, but I'm missing a piece.

A: 

Somehow you need a reference to your CastleCrash object available to call from your actionListener.

You probably want to subclass JFrame, or whatever is containing your JButton such that it has your both your main method and a CastleCrash property that can then be referenced from your anonymous inner class Actionlistener.

BUT - be careful, you look like you are calling what will be a long running method from within the GUI event thread (where the action listener will called). This is generally a bad idea, you will case your GUI to become unresponsive.

See http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html especially the bit on SwingWorker class for ideas on how to avoid that problem.

Alex Stoddard
+1  A: 

One way to reference things in an anonymous class is using the final keyword:

  public static void main(String[] args) {
    final Object thingIWantToUse = "Hello";

    JButton button = new JButton("Click");
    button.addActionListener(new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        System.out.println(thingIWantToUse);
      }
    });

    JFrame frame = new JFrame();
    frame.setLayout(new FlowLayout());
    frame.add(button);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
  }

Alternatively, you can access members (variables or methods) of an enclosing type:

public class ActionListenerDemo2 {
  private final JFrame frame = new JFrame();
  private Object thingIWantToUse = "Hello";

  public ActionListenerDemo2() {
    JButton button = new JButton("Click");
    button.addActionListener(new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        thingIWantToUse = "Goodbye";
        System.out.println(thingIWantToUse);
      }
    });
    frame.setLayout(new FlowLayout());
    frame.add(button);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
  }

  public static void main(String[] args) {
    new ActionListenerDemo2().frame.setVisible(true);
  }
}
McDowell
I don't quite understand the second option you describe. How is it possible to access the methods of an enclosing type?
Myles
If you added a method `doFoo()` to `AnctionListenerDemo2`, then you could call it from inside `actionPerformed`. `actionPerformed` belongs to the anonymous inner class implementation of the interface `ActionListener`. Intro to nested classes here: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html
McDowell
+1  A: 

McDowell already answers practically with good examples on how to access variables from event listeners (or anonymous inner classes in general). There is however a more general Sun resource on Event Listeners in Swing that is canonical and a good overview of all the caveats to take into account when writing them.

Boris Terzic