April 24, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Notifications in a Java/Swing Application

  • June 26, 2007
  • By Rob Lybarger
  • Send Email »
  • More Articles »

Overview

In a previous article, I demonstrated how to use an "application controller" object to separate the control logic from the user interface classes in a basic Java/Swing application. The idea there was to provide methods in the controller class that managed application behavior in a centralized location. The various user interface elements (buttons and so forth) connected to these methods, typically via a simple anonymous listener registration. Although the application controller technique works quite well, I wanted to illustrate how to implement a "notification center" object into your application. (In the interest of full disclosure, this article is influenced by my recent forays into learning Cocoa programming in OS X. That framework has some excellent ideas that Java could borrow from.)

As with my past articles, I assume a comfortable familiarity with the Java language. I will present some code snippets in this article while showing a simplified demonstration. The full source code for the demonstration is available for download.

The purpose of a notification center is slightly different than the controller object, although they can work nicely when paired up. Recall that the application controller object was designed for a one-to-one level of interaction between the controller and a certain, known user interface element (conceptually: "disable this button, then clear the value in that textbox"). By contrast, the notification center is designed for a one-to-many level of interaction.

The difference can be thought of this way: In a room of a hundred people, you can tell each of the ten interested parties one at a time in private, or you can just make an announcement to the entire room. (See also unicast versus multicast.) When utilizing a notification center, you choose to leave the details of some action (such as the user moving a slider knob) up to the interested recipients to decide for themselves what to do. A button might need to disable itself in response to some event, for example. In short, this is one more way to reduce hard-wired dependencies between different components of the application. The effect is so close to the existing Swing event model that this demo actually co-opts the PropertyChange events. (However, don't limit your thinking entirely to button press events!)

The Demo Application

To illustrate the concept, a demonstration app needs to be explained. I'll show how to arrange for notification of the change in value of a JSlider component, such as happens when the user moves the slider knob. The application controller I praised last time is not present in this demo—this choice is mainly intended to more clearly illustrate the differences.

Figure 1: A quick (if rough) sample might look like this.

The requirements for this application are fairly simple: When the slider's value changes, the text field should display the current value of the slider, and the grey box component should change its level of grayness. (When the slider is fully to the left, the box is black; when fully to the right, the box is white.) However, you desire no hard-wired connections among any of these components: If the text field were simply removed from the application entirely, the rest should continue functioning correctly without any adverse "null pointer" effects.

The Notification Object

The code needed for this is actually rather straightforward. Provide a class with an ordinary event-style "add/remove" method pair to register the listeners for some named event (more on this shortly) and a "fire" method to cause a notification for some named event to be distributed to all currently registered listeners. The sample code for this article (available in the related files) basically takes the existing "PropertyChangeListener" concept and puts it to extended use. However, feel free to use a different Event/Listener combination (including your own) as needed.

The "named event" mentioned above is up to you to provide. It is any unique string value that clearly distinguishes one value (or property) change from another. For this demo, the slider uses the "fire" method in the notifier, using "sliderAdjusted" as the distinguishing name. The text field and the color box are registered with the notifier as wanting to receiving notifications for the "sliderAdjusted" event. The actual integer value of the slider is passed along for the receivers to process however they see fit.

Showing only the public members, the skeleton code for the Notifier class (implemented as a singleton) in this demo looks like:

public class Notifier {

   public static Notifier getInstance() { ... }

   public void addPropertyChangeListener(
      String propertyName, PropertyChangeListener listener) { ... }

   public void removePropertyChangeListener(
      String propertyName, PropertyChangeListener listener) { ... }

   public void firePropertyChange(
      Object src, String propertyName, Object newValue) { ... }

}

Usage

The JSlider object emits a ChangeEvent to registered ChangeListeners whenever the value is adjusted. This demo connects an anonymous class listener implementation to have the notifier fire off the previously mentioned "sliderAdjusted" events:

slider = new JSlider(0,100);
slider.addChangeListener(new ChangeListener() {
   public void stateChanged(ChangeEvent e) {
      JSlider src = (JSlider)e.getSource();
      if (src.getValueIsAdjusting()) {
         return;
      }
      Integer newValue = new Integer(src.getValue());
      Notifier.getInstance().firePropertyChange(src,
         "sliderAdjusted",newValue);
   }
});

Note how the JSlider is simply configured to tell the notification object that its value has been changed. It doesn't know whether anyone else in the application even cares. Fortunately, a couple other pieces do. The text field (and, not shown here, the color box) is set up to receive the effects of a "sliderAdjusted" property change event:

textField = new JTextField(20);
Notifier.getInstance().addPropertyChangeListener(
   "sliderAdjusted", new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent e) {
         textField.setText("Slider Value = " + e.getNewValue());
      }
   }
);

The color box makes a similar registration with the notification center, although the effects are a little different. (The slider's value, between 0 and 100, is turned into a corresponding Color for that shade of gray, and the box is repainted.) What I have deftly not shown are the details in the Notifier class itself: It is a fairly basic matter of storing the listeners for a given event name into a Vector, and storing that Vector into a HashMap, using the event name as the key. The "fire" method just accesses the appropriate Vector object and notifies each listener in turn. It should bear noting that the amount of work each listener does should be kept minimal to prevent impacting the event dispatch thread too much. (This is the same warning as with any standard Swing event handlers, however.)

     

Figure 2: A couple of illustrations of this demo application after the slider has been moved.





Page 1 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel