|
|
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 4 of 6

Figure 4a. A listener listens for window close events

Figure 4b. A dialog box lets users save changes
The application shown in Figure 4 is listed in Example 4:
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
import java.util.*;
public class Test extends JFrame {
private JDesktopPane desktopPane = new JDesktopPane();
public Test() {
Container contentPane = getContentPane();
contentPane.add(desktopPane, BorderLayout.CENTER);
desktopPane.setLayout(new FlowLayout());
JInternalFrame jif = new JInternalFrame(
"A Window with a Vetoable Change Listener", // Title
false, // Resizable
true); // Closable
jif.setPreferredSize(new Dimension(400, 350));
jif.show();
jif.addVetoableChangeListener(new CloseListener());
desktopPane.add(jif);
}
public static void main(String args[]) {
GJApp.launch(new Test(),
"Vetoing Internal Frame Closing",
300,300,550,400);
}
}
class CloseListener implements VetoableChangeListener {
private Test applet;
public void vetoableChange(PropertyChangeEvent e)
throws PropertyVetoException {
String name = e.getPropertyName();
if(name.equals(JInternalFrame.IS_CLOSED_PROPERTY)) {
Component internalFrame = (Component)e.getSource();
Boolean oldValue = (Boolean)e.getOldValue(),
newValue = (Boolean)e.getNewValue();
if(oldValue == Boolean.FALSE &&
newValue == Boolean.TRUE) {
int answer = JOptionPane.showConfirmDialog(
internalFrame, // ParentComponent
"Save Changes?", // Message
"Unsaved Changes", // Title
JOptionPane.YES_NO_CANCEL_OPTION);
if(answer == JOptionPane.CANCEL_OPTION) {
throw new PropertyVetoException("close cancelled", e);
}
}
}
}
}
class GJApp extends WindowAdapter {
// Application class not listed here for the sake of brevity.
}
The difference between regular change listeners and vetoable change listeners is that the latter can throw a PropertyVetoException(), as illustrated in Example 4. Throwing the exception rolls back the change, in this case, the window close operation, so
the window stays open.
Now that you know how to use the Observer pattern's Swing and JavaBeans implementations, let's see how you can implement the Observer pattern in your own code.
This section extends an example from a previous Java Design Patterns column, "Take Control with the Proxy Design Pattern." In that example, I implemented a proxy for Swing image icons that creates images on demand. In this section, I extend that example by implementing the Observer pattern: when the proxy finishes loading its image, it fires a property change event, and a listener displays a dialog box.
The application, shown in Figures 5a, 5b, and 5c, contains a regular Swing image icon on the left and an image icon proxy
on the right. The icon loads its image when it's created, so it appears when the application starts. The proxy, on the other
hand, draws a rectangle around its perimeter and displays the message Loading image... until the image loads. Subsequently, when the image loads, the proxy paints the image and fires a property change event.
An application-specific listener reacts to the property change event by displaying a dialog box, as shown in Figure 5c.