Java Swing Example using Observer and Observable
Jul 23, 2013
This blog post is about using Java Observable class and Observer interface using a Swing GUI based example. This post includes notes on the related Model View and Observer design principles.
The Observer and Observable are defined in Java SE's java.util package. These API is used to implement an example application.
1. The Example
The example is a Java Swing application. This has two GUI windows, an Observable data class and a starter program.
1.1. Main Window
This window displays a text message, whenever data is changed in an Observable object. This is a Observer object. This implements the Observer interface and its update() method.
1.2. Dialog Window
This window has a button, and when clicked (action) updates (data in) an Observable object. The class creates an Observable object and adds (or registers) the Main Window as an Observer (to the Observable).
1.3. Message Observable
This class extends Observable; has a method to notify (or inform) of (the data) changes in this.The Observer object (Main Window) is informed of any changes to this.
1.4. Example Application Starter
This class starts the application; displays the two GUI windows. Close the Main Window to exit the application.
1.5. The Example Application's GUI
- Main Window, at the start of application.
- Dialog Window, with the button.
- Main Window, after the button is clicked in Dialog Window. Each time the button is clicked, the text with a click counter is displayed in the Main Window.
1.6. Example Application's Code
The example code ExampleAppStarter.java is listed at the end of this post.
2. The API
2.1. Observer Interface
This is informed of changes in a Observable object (and, can receive notifications from multiple Observable objects).
This has only one method, public void update(Observable ob, Object data)
. The Object argument data
can be a null value. The Observable argument ob
can be used to identify the type, in case this Observer gets notifications from multiple Observable objects; for example:
if (ob instanceof MessageObservable) {
// do something
}
else {
// print error
}
2.2. Observable Class
This represents an Observable object. This class can be subclassed.
When an Observable object changes, the notifyObservers()
method informs all the Observer objects (which are added to this or registered with this). The Observer object's update()
method receives these notifications and optional data.
Useful methods in this class: addObserver(), removeObserver(), notifyObservers(), setChanged() and hasChanged().
An Observable object can have multiple Observer objects registered with it.
3. Design Notes
Observer and Model View Design Principles:
3.1. In the Model-View paradigm:
- The data is represented by the Model, and the View by the visual component.
- In a MVC (Model View Controller), the Controller provides the communication between the Model and View objects. The Controller may be a separate class or within the model or view.
In the example application, the Message Observable is the data and the Main Window is the view. The Dialog Window is the controller.
3.2. The Observer design pattern:
- An object, called the subject, maintains a list of its dependents called Observers, and notifies them automatically of any state changes.
- The pattern promotes loose coupling to the subject; a subject doesn’t know the details of its Observer.
- This is mainly used for event handling applications or systems.
In the example application, the data is the subject and the display is the Observer. The display receives changes in that data.
3.3. In Java:
The design principles are not only applied for connecting UIs and model objects; in Java Swing the GUI objects like a JButton publish GUI-related events. In an application:
- A GUI component or a Java Bean is a model (or subject)
- A listener class is a Observer
- The listener is registered with the model, and is notified when the model is changed
These are two of the listener interfaces:
java.awt.event.ActionListener
: This is the listener interface for receiving action events from a GUI component.java.beans.PropertyChangeListener
: This is a listener interface for receiving property change events (whenever a bean changes a bound property).java.beans.PropertyChangeSupport
is a utility class that can be used by beans, and a property change listener can be added (or registered) to the bean.
4. References
Link to Java SE 7 API: http://docs.oracle.com/javase/7/docs/api/index.html?overview-summary.html
5. ExampleAppStarter.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class ExampleAppStarter {
public static void main(String [] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new ExampleAppStarter().start();
}
});
}
private void start() {
MainWindow m = new MainWindow();
new DialogWindow(m);
}
} // ExampleAppStarter
class MainWindow implements Observer {
private JLabel label;
@Override // Observer interface's implemented method
public void update(Observable o, Object data) {
label.setText((String) data); // displays new text in JLabel
}
MainWindow() {
JFrame frame = new JFrame("Main Window");
frame.getRootPane().setBorder(
BorderFactory.createEmptyBorder(20, 20, 20, 20));
label = new JLabel("Click button in Dialog...");
label.setFont(new Font("Dialog", Font.PLAIN, 20));
frame.add(label);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 150);
frame.setLocation(200, 200);
frame.setVisible(true);
}
} // MainWindow
class DialogWindow {
private int clicks;
DialogWindow(MainWindow mainWindow) {
// Create Observable and add Observer
final MessageObservable observable = new MessageObservable();
observable.addObserver(mainWindow);
// Display Dialog
JFrame dialog = new JFrame("Dialog");
JButton button = new JButton("Press me");
button.setFont(new Font("Dialog", Font.PLAIN, 20));
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String data = "button clicked in dialog [" + ++clicks + "]";
observable.changeData(data);
}
});
dialog.add(button);
dialog.setSize(250, 150);
dialog.setLocation(600, 200);
dialog.setVisible(true);
}
} // DialogWindow
class MessageObservable extends Observable {
MessageObservable() {
super();
}
void changeData(Object data) {
setChanged(); // the two methods of Observable class
notifyObservers(data);
}
} // MessageObservable
6. Download
Download source code here: SwingObserverExample.zip
Return to top