Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 3 of 6
In Example 1, I used inner classes to implement the application's listeners, because the listener classes were tightly coupled to their enclosing class; however, you can implement listeners any way you desire. One of the most popular choices for handling user interface events is the anonymous inner class, which is a class with no name that's created in-line, as demonstrated in Example 2:
...
public class Test extends JFrame {
...
public Test() {
...
model.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
String s = Integer.toString(model.getValue());
readOut.setText(s + "%");
readOut.revalidate();
}
});
}
...
}
class ImageView extends JScrollPane {
...
public ImageView(final ImageIcon icon, BoundedRangeModel model) {
...
model.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
BoundedRangeModel model =
(BoundedRangeModel)e.getSource();
if(model.getValueIsAdjusting()) {
int min = model.getMinimum(),
max = model.getMaximum(),
span = max - min,
value = model.getValue();
double multiplier = (double)value / (double)span;
multiplier = multiplier == 0.0 ?
0.01 : multiplier;
Image scaled = originalImage.getScaledInstance(
(int)(originalSize.width * multiplier),
(int)(originalSize.height * multiplier),
Image.SCALE_FAST);
icon.setImage(scaled);
panel.revalidate();
}
}
});
}
}
Example 2's code is functionally equivalent to Example 1's code; however, the code above uses anonymous inner classes to define the class and create an instance in one fell swoop.
Using anonymous inner classes as shown in the previous example was very popular with developers, so starting with Java 2 Platform,
Standard Edition (J2SE) 1.4, the JavaBeans specification has taken the responsibility for implementing and instantiating those
inner classes for you with the EventHandler class, as shown in Example 3:
import java.beans.EventHandler;
...
public class Test extends JFrame {
...
public Test() {
...
model.addChangeListener(EventHandler.create(
ChangeListener.class, this,
"updateReadout"));
}
...
public void updateReadout() {
String s = Integer.toString(model.getValue());
readOut.setText(s + "%");
readOut.revalidate();
}
}
...
Using reflection, the static EventHandler.create() method creates a listener that implements the specified interface by invoking the specified method (in this case, updateReadout()) on the specified target (this). You lose some type safety with this approach, but perhaps contrary to your intuition, the EventHandler.create() can be faster than handcoding listeners because the EventHandler class can cache listeners.
Before we discuss implementing the Observer pattern in your code, let's examine a variation of the Observer pattern where observers can veto proposed events.
Most of the time, listeners (a.k.a. observers) react to events that have already occurred. But sometimes, listeners need veto power to prevent an upcoming event from occurring. For example, consider the common scenario depicted in Figures 4a and 4b: a listener listens for window close events (Figure 4a) and displays a dialog box that lets the user save changes (Figure 4b). If the user clicks the Cancel button, the listener will veto the window close event.