views:

383

answers:

2

I have a class (simulation) which creates an instance of another class (GUI). Inside the class GUI there is a button (start) which has an actionlistener attached to it.

I need this actionlistener to start a timer in simulation but I can't figure out how to do it.

Code in Class Simulation:

public class Simulation{

private static JFrame frame;
private static GUI control;
public static Integer xcontrol = 100, ycontrol = 100;

public Timer timer;
public int steps;

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

}

public Simulation() {

frame = new JFrame("Action Listener Test");
frame.setLayout(new BorderLayout(1,0));

control = new GUI (xcontrol, ycontrol);
frame.getContentPane().add(control , BorderLayout.CENTER);

frame.setResizable(false);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}


public void StartTimer() {
    timer.start();
    System.out.println("It worked!"); 
}

Code in Class GUI:

  panel1.add(button1a);

   button1a.addActionListener(new ActionListener() {
    public void actionPerformed (ActionEvent event) {
     Simulation.StartTimer();
     }
    } );

The error Eclipse tells me there is, is that for "Simulation.timer.start();" :

Cannot make a static reference to the non-static method StartTimer() from the type Simulation.

However the method StartTimer() cannot be static as this seems to break the timer...

Any help would be very appreciated.

A: 

Pass this as an argument to the GUI constructor.

In general it is best to avoid such cyclic references. Both the GUI and Simulator become dependent upon one another. The essence of the solution is to separate out the GUI from the interesting domain-specific behaviour.

(BTW: I would strongly avoid using static variables for anything other than constants. Also avoid non-private instance variables. But point for not extending JFrame!)

There is some hideous boilerplate that you should add to prevent multithreading.

public static void main(final String[] args) {
    java.awt.EventQueue.invokeLater(new Runnable() { public void run() {
                Simulation sim = new Simulation();
    }});
}
Tom Hawtin - tackline
I apologise, I made a mistake in the code I posted. The "main constructor" was actually a "Simulation" instructor. As such sim is itself a "Simulation" object, so it couldn't be an argument for the GUI constructor I don't think...
Myles
A: 

What I would do is have your GUI class expose the button via a getButton() method, then after creating the GUI object, your Simulation class can add its own ActionListener to the button, e.g. control.getButton().addActionListener(new ActionListener()... etc.

cgull