Your problem is that you don't use correct architecture pattern. You should separate your business logic from your presentation. Also you should store variables (like time_left
) in model, not in the controller (i.e. ActionListener
). Please read about: Model View Controller pattern. It's a basic pattern and it'll solve most of yours problems.
Basic Example
Editor.java - main class
public class Editor {
public static void main(String[] args) {
Model model = new Model();
View view = new View(model);
new Controller(model, view);
}
}
View.java
public class View extends JFrame {
private Model model;
private JButton btn;
public View(Model model) {
this.model = model;
this.btn = new JButton("Test");
}
public void addViewControlListener(ActionListener al){
btn.addActionListener(al);
}
}
Controller.java
public class Controller {
public Controller(Model model, View view) {
view.addViewControlListener(new ViewControlListener(model, view));
}
}
ViewControlListener.java - implements ActionListener
public class ViewControlListener implements ActionListener {
private Model model;
private View view;
public ViewControlListener(Model model, View view){
this.model = model;
this.view = view;
}
public void actionPerformed(ActionEvent e) {
//update model
//refresh view
}
}
As you can see I have the one place (Controller.java
) where I create listeners and add
these to components in view. You created multiple instances of the same listeners and lost control.
Also my ActionListener
(ViewControlListener.java
) holds instances of model and view, so it can update variables in model and refresh view.
Your application
And now something more about your application. You need thread (not realy action listener) that would decrement time variable and update view to show actual state (but only when game is active).
So you could create in model leftTime
and isActive
variables with setters and getters:
private int leftTime;
private boolean isActive;
public int getLeftTime() {
return leftTime;
}
public void setLeftTime(int leftTime) {
this.leftTime = leftTime;
}
public void decLeftTime() {
this.leftTime--;
}
public boolean isActive() {
return isActive;
}
public void setActive(boolean isActive) {
this.isActive = isActive;
}
And create thread that decrement time every second and repaint the view:
public class Timer extends Thread {
private Model model;
private View view;
public Timer(Model model, View view) {
this.model = model;
this.view = view;
}
public void run() {
while(true) { //could be better
if(model.isActive()) {
model.decLeftTime();
view.repaint();
}
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Then create and start that thread in Controller:
public class Controller {
public Controller(Model model, View view) {
view.addViewControlListener(new ViewControlListener(model, view));
...
Timer timer = new Timer(model, view);
timer.start();
}
}
In view you would add some component that shows left time from model and that's it.
PS do not forget set leftTime
on game start.