I've created a series of classes to try and figure out Observer patterns and am having some trouble. The two classes in the observer/observed relationship are ClockPanel, and TheTimer. TheTimer is a (swing) timer which keeps track of time from start in seconds. ClockPanel is a GUI (swing) which has a button to start the timer and a JLabel which I want to display the time.
The goal of my observer pattern: take the value being created in TheTimer and print it on my GUI.
The current problem: The timer is updating the time just fine, but I do not seem to understand how to update the value in my GUI.
I found a question similar to this one in a C# discussion, but the problem was more nuanced and way over my head.
Here are the five classes which comprise the program: 1. The GUI-ClockPanel
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class ClockPanel implements Observer {
JFrame frame;
JPanel panel;
JButton sbutton;
JLabel label;
@Override
public void update(int counter) {
String clockval = String.valueOf(counter);
label.setText(clockval);
}
public ClockPanel() {
frame = new JFrame();
frame.setSize(100, 100);
panel = new JPanel();
label = new JLabel();
TheTimer myTimer = new TheTimer();
sbutton = new JButton("start");
sbutton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
myTimer.StartTimer();
}
});
frame.setLayout(new FlowLayout());
frame.add(panel);
frame.add(sbutton);
frame.add(label);
frame.setVisible(true);
}
}
2. The Swing Timer-TheTimer
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JPanel;
import javax.swing.Timer;
public class TheTimer extends JPanel implements Subject {
private ActionListener action;
private Timer Time;
private int delay = 1000;
private ArrayList<Observer> observers = new ArrayList<Observer>();
private int counter = 0;
public TheTimer() {
action = new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println(counter);
counter++;
setCounter(counter);
}
};
}
public void StartTimer() {
Time = new Timer(delay, action);
Time.setInitialDelay(0);
Time.start();
}
public int getCounter() {
return counter;
}
public void setCounter(int counter) {
this.counter = counter;
notifyObservers();
}
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer ob : observers) {
System.out.println("Notifying ClockPanel on change in counter value");
ob.update(this.counter);
}
}
}
3. The Observer-Observer
public interface Observer {
public void update(int counter);
}
4. The Observer-related methods-Subject
public interface Subject {
public void registerObserver(Observer observer);
public void removeObserver(Observer observer);
public void notifyObservers();
}
5. The Main-TestMain
import javax.swing.SwingUtilities;
public class TestMain {
public static void main(String args[]) {
ClockPanel panel = new ClockPanel();
TheTimer timer = new TheTimer();
timer.registerObserver(panel);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new ClockPanel();
}
});
}
}
You have two TheTimer
objects: one in ClockPanel
, the other in TestMain#main()
.
You need to remove the timer from (say) main()
and add:
myTimer.registerObserver(this);
to your ClockPanel
constructor.