So far, we have treated components as single, self-contained GUI building blocks. And indeed, components can be written to be entirely self-contained. However, neither AWT nor Swing components are actually self-contained. As I mentioned earlier, each AWT component is simply a frontend for an underlying native user-interface object. AWT delegates all the display and event processing--that is, the look-and-feel--to these native GUI elements.
Swing components are not self-contained either. Most Swing components rely on two other objects: a user-interface (UI) delegate object and a model object. Swing supports a pluggable look-and-feel architecture, which means that a Swing application can control the appearance and behavior of its user-interface. Thus, a Swing application can be displayed in a platform-independent way or in a way that mimics the native look-and-feel of the underlying platform, for example. In order to implement the pluggable look-and-feel architecture, every Swing component must delegate its display and event-handling functions to a separate object: the UI delegate. Fortunately, you can use Swing without ever thinking about the pluggable look-and-feel. That's because, when you create a Swing component, an appropriate UI delegate object is automatically created for it.
The model object for a Swing component is responsible for storing the state of the component. For example, the JToggleButton uses an implementation of the ButtonModel interface as its model. This ButtonModel object remembers whether the button is currently selected. As another example, the JScrollBar, JSlider, and JProgressBar components use a BoundedRangeModel object to keep track of their state. This state includes minimum, maximum, and current values.
Most Swing components automatically create the model objects they rely on, so you can use these components without ever worrying about model objects. When working with more complicated components, however, models become more important. For example, the JTree component uses a javax.swing.tree.TreeModel object to represent the data it is to display. The JTree component can be used to display many kinds of hierarchically structured data. JTree does not require you to convert your data into some predefined data format, however. Instead, you implement the TreeModel interface in a way that allows JTree to understand the data. For example, to use a JTree component to display files in the filesystem, you might define a FileTreeModel class that implements the TreeModel interface on top of the capabilities of the java.io.File class. Or, if you want to use JTree to display the structure of an XML document, you might create an implementation of TreeModel that works with the parse tree returned by an XML parsing class.
The JTable component is another for which the use of a separate model object is particularly important. JTable can be used to display a tabular view of data, even when that data is not tabular by nature. To do so, you implement the javax. swing.table.TableModel interface to provide a neat, tabular view of the data.
One advantage of this model object approach, where the actual data is separated from the component's view of that data, is that you can define multiple views of the same data. For example, if you have a large set of tabular data that implements the TableModel interface, you can have two or more JTable components that display different portions of that data at the same time. When you are writing an application that manipulates complex data structures, you should consider designing these structures so that they implement appropriate Swing model interfaces. If you do this, you'll be able to trivially display your data using Swing components. See Chapter 3, "Swing Programming Topics", for more information about implementing TreeModel and TableModel.
Copyright © 2001 O'Reilly & Associates. All rights reserved.