Swing is one of the major improvements in the JDK between versions 1.1 and 1.2. It is also one of the key APIs of the Java Foundations Classes (JFC). What makes Swing so important is the power that it provides in developing GUIs for applets and applications. The number and quality of the GUI controls provided by Swing is unrivaled by any other GUI toolkit.
Up until now, you have been developing your applet and application GUIs using the traditional GUI controls of the AWT. In this chapter, you'll be introduced to the GUI controls of Swing. You'll learn what Swing is, where it comes from, and its relationship to the AWT and the JFC as a whole. You'll cover the Swing component hierarchy and learn about the Swing packages. You'll then develop an example Swing-based GUI. When you finish this chapter, you will be thoroughly introduced to Swing. The following chapter will then expand upon your Swing programming skills.
Swing is a major component of the JFC, which is the result of a large collaborative effort between Sun, Netscape, IBM, and other companies. Swing provides a large number of useful GUI controls that originated with Netscape's Internet Foundations Classes (IFC). The Swing components go far beyond the IFC, to the point where there is no visible resemblance between Swing components and those of the IFC. Swing also provides the capability to quickly and easily change the look and feel (L&F) of a single component or group of components. This capability, known as pluggable look and feel (PL&F), is a hallmark feature of Swing. Chapter 14, "Changing the Look and Feel of Your Swing Components," focuses on Swing's PL&F features.
NOTE: To make optimal use of Swing, your video card should be set to 16-bit or higher color. This setting supports 65,536 color combinations.
Figure 12.1 shows the relationship between Swing, the AWT, and the JFC. The JFC subsumes and extends the original AWT and consists of the following major APIs:
Although Swing is separate from the AWT, it is implemented in terms of basic AWT classes. The AWT provides the interface between the underlying native windowing system and the Java GUI components. Swing uses this interface, but does not rely on AWT components that make use of native windowing system objects. Instead, Swing components are written in pure Java. This provides significant advantages. It allows Swing components to be independent of the native windowing system, which means they can run on any windowing system that supports the AWT. It also allows Swing components to be independent of any limitations of the native windowing systems. This independence allows Swing to control and tailor its look and feel--hence the emergence of PL&F.
FIGURE 12.1. Swing, IFC, JFC, and AWT.
Swing also provides a pure Java implementation of many of the traditional AWT components. These components have the same functionality as the AWT components and all of the advantages of Swing. Swing is compatible with the AWT, and Swing components can be used interchangeably with AWT components. However, Swing components can only be used with the JDK 1.1 event model. They do not support the JDK 1.0 event model.
NOTE: The latest version of Swing can be found at http://www.javasoft.com/products/jfc/index.html. Swing is packaged as part of the JFC.
Swing consists of 9 packages, and hundreds of classes and interfaces. However, the JComponent class of com.sun.java.swing is the top-level class of the Swing component hierarchy. As such, it is a good starting point for learning about Swing components. The JComponent class is a subclass of the java.awt.container class, and is therefore both a component and container in the AWT sense. Because JComponent is the superclass of all Swing components, all Swing components descend from java.awt.Container and java.awt.Component.
Figure 12.2 shows the Swing component hierarchy. The first thing that you should notice is that all components begin with the letter J, followed by the type of component supported by the class. JComponent has the following direct subclasses:
FIGURE 12.2. Swing component hierarchy.
You'll see visual examples of many of these components later in this chapter
and in the following chapter.
Swing is a large API consisting of 9 packages and numerous classes and interfaces. Most of the Swing components are contained in the com.sun.java.swing package, which also provides classes and interfaces that support and manage the GUI components. The com.sun.java.swing.border package provides a number of interesting borders that can be used with Swing components. These borders help to tailor the look and feel of component sets.
The com.sun.java.swing.event package defines the events and event listeners used by Swing components. It is a good idea to look over the list of events and event listeners to get a feel for the types of user interactions supported by Swing.
The com.sun.java.swing.table package provides classes and interfaces that support the feature rich and flexible JTable object. You use these classes and interfaces to tailor a table's display features.
The com.sun.java.swing.text packages provides several classes and interfaces that support text components. These classes and interfaces control the caret, highlighting, formatting, and other aspects of text that is entered and edited within text components.
The com.sun.java.swing.text.html package contains the single HTMLEditorKit class. This class supports the implementation of a simple but powerful HTML editor. The com.sun.java.swing.text.rtf package is similar to the com.sun.java.swing.text.html package. It contains the single RTFEditorKit class, which provides the capability to edit Rich Text Format (RTF) text.
The com.sun.java.swing.tree package provides classes and interfaces that support the use of the JTree component.
The com.sun.java.swing.undo package provides support for undo and redo operations.
The com.sun.java.swing.plaf provides support for Swing's pluggable look-and-feel features.
Now that we've covered the components and packages that compose the Swing API, you'll develop a sample program that shows off some of Swing's features. You'll run the program first, to get an idea of what it does, and then you'll examine the Swing code used in its implementation.
Listing 12.1 shows the source code of the SwingStart program. Compile this program and run it. It displays the GUI shown in Figure 12.3. You'll notice four tabs labeled Buttons, Bars, Lists, and Table. You'll also notice two graphical buttons. Move your mouse over any of the tabs. After a second or two, an information tip is displayed, as shown in Figure 12.4. Move your mouse over each tab to see the tip associated with that tab.
FIGURE 12.3. The initial display of the SwingStart program.
FIGURE 12.4. Tips
are displayed when you move your mouse over a tab.
The Buttons tab shows two buttons. The button on the left is a standard button, but it is enhanced with a printer image. Wouldn't a button like this be more informative to a program user than a simple text button? The button on the right provides an extra capability--the button retains its state. When you click the button, it sticks in the in position. When you click it again, the button moves back out.
Click on the Bars tab. A slider and a progress bar are displayed, as shown in Figure 12.5. Use your mouse to move the slider, and the progress bar is updated to reflect the new slider position. Sliders and progress bars provide users with a fine level of control over a program parameter and display progress toward the completion of a task.
FIGURE 12.5. The Bars tab shows examples of Swing's slider and progress bar controls.
FIGURE 12.6. A Swing list can contain icons.
Click on the Lists tab. The icon list, shown in Figure 12.6, is displayed. Click on any of the images to select it from the list. As you can see, Swing provides excellent integration of images into GUI controls.
FIGURE 12.7. Swing makes it easy to create advanced tables.
Click on the Table tab. The cost table, shown in Figure 12.7, is displayed. Swing
tables not only provide the capability to display tabular information, but they can
also be used to create tables that can be edited by users.
The GUI controls shown in the SwingStart program are just a small sample of the GUI capabilities of Swing. However, they are enough to introduce you to Swing programming, as discussed in the next section.
import java.awt.*; import java.awt.event.*; import com.sun.java.swing.*; import com.sun.java.swing.event.*; import com.sun.java.swing.border.*; public class SwingStart extends Frame { public static int WIDTH = 450; public static int HEIGHT = 450; public static String TITLE = "SwingStart"; // Swing components JTabbedPane tabbedPane = new JTabbedPane(); JPanel buttonPanel = new JPanel(); JPanel barPanel = new JPanel(); JPanel listPanel = new JPanel(); JPanel tablePanel = new JPanel(); JPanel[] panels = {buttonPanel,barPanel,listPanel,tablePanel}; Icon worldIcon = new ImageIcon("world.gif"); Icon printerIcon = new ImageIcon("printer.gif"); Icon leaf1Icon = new ImageIcon("leaf1.gif"); Icon leaf2Icon = new ImageIcon("leaf2.gif"); Icon leaf3Icon = new ImageIcon("leaf3.gif"); Icon[] leaves = {leaf1Icon, leaf2Icon, leaf3Icon}; JButton printerButton = new JButton("Print",printerIcon); JToggleButton worldButton = new JToggleButton("Connect",worldIcon,true); JList leafList = new JList(leaves); JSlider slider = new JSlider(JSlider.VERTICAL, 0, 100, 60); JProgressBar progressBar = new JProgressBar(); String[] columns = {"Product ID","Description","Price"}; Object[][] cells = {columns,{"zvga-1234","Video Card","$50"},
{"56m-11","56K Modem","$315"},
{"dc-10","Net Card","$499"}}; JTable table = new JTable(cells,columns); { super(TITLE); addWindowListener(new WindowHandler()); buildGUI(); setSize(WIDTH,HEIGHT); setBackground(Color.darkGray); show(); } void buildGUI() { // Set up tabbed pane String[] tabs = {"Buttons","Bars","Lists","Table"}; String[] tabTips = {"A Button and a Toggle Button", "A Slider and a Progress Bar", "An Icon List", "A Cost Table"}; for(int i=0;i<tabs.length;++i) { panels[i].setBackground(Color.lightGray); panels[i].setBorder(new TitledBorder(tabTips[i])); tabbedPane.addTab(tabs[i],null,panels[i],tabTips[i]); } addComponentsToTabs(); add("Center",tabbedPane); } void addComponentsToTabs() { setupButtonPanel(); setupBarPanel(); setupListPanel(); setupTablePanel(); } void setupButtonPanel() { printerButton.setBackground(Color.white); worldButton.setBackground(Color.white); buttonPanel.add(printerButton); buttonPanel.add(worldButton); } void setupBarPanel() { slider.setMajorTickSpacing(10); slider.setMinorTickSpacing(5); slider.setPaintTicks(true); slider.addChangeListener(new SliderHandler()); progressBar.setOrientation(JProgressBar.HORIZONTAL); progressBar.setMinimum(0); progressBar.setMaximum(100); progressBar.setValue(60); progressBar.setBorderPainted(true); barPanel.add(new JLabel("Slider")); barPanel.add(slider); barPanel.add(new JLabel("Progress Bar")); barPanel.add(progressBar); } void setupListPanel() { leafList.setFixedCellHeight(123); listPanel.add(leafList); } void setupTablePanel() { tablePanel.add(table); } public static void main(String[] args) { SwingStart app = new SwingStart(); } public class WindowHandler extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } public class SliderHandler implements ChangeListener { public void stateChanged(ChangeEvent e) {
progressBar.setValue(slider.getValue()); } }
}
The first thing that you should notice about SwingStart is that it imports the com.sun.java.swing (Swing components), com.sun.java.swing.event (Swing event handling), and com.sun.java.swing.border (custom borders) packages. The SwingStart program extends the Frame class of java.awt. Swing provides its own window classes that extend java.awt. You'll learn about these classes in the following chapter. SwingStart uses the Frame class to show how Swing and AWT components can be used interchangeably.
The SwingStart class begins by declaring a few constants used to define the window size and title. After that, it declares and initializes a number of variables used to implement Swing components. These variables are used as follows:
The SwingStart constructor invokes the superclass constructor to set the window's title, adds a window event handler, and invokes the buildGUI() method to build the program's graphical user interface. The setSize() method is used to set the window's size, and the setBackground() method sets the window's background color to dark gray. Finally, the show() method is invoked to cause the window to be displayed.
The buildGUI() method sets up the tabbed pane that controls the program's display. It creates an array of tab labels and tips associated with those labels. It then uses a for statement to set the background color and border of each panel. The border used is a TitleBorder object. This border constructs an etched box around the panel's contents and displays a title in the upper-left corner of the pane. Refer to Figures 12.3 through 12.7 for examples of how the border is displayed. Each of the panels is then added to a tab via the addTab() method, which takes the names of the tabs, an icon, the objects to be added to each tab, and the tab tips as parameters. The addComponentsToTabs() method is invoked to add components to the panels of each tab. The tabbed pane is then added to the center of SwingStart's frame.
The addComponentsToTabs()method simply invokes other methods to set up the Buttons, Bars, Lists, and Table panes.
The setupButtonPanel() method adds the printer and world buttons to the Buttons tab. It sets the background color of the buttons to white and then adds the buttons to the pane. No event handling is provided for the buttons.
The setupBarPanel() method sets parameters for the slider and progress bar, adds an event handler for the slider, and then adds the slider and progress bar to the Bars tab. The setMajorTickSpacing() and setMinorTickSpacing() methods are used to add tick marks to the slider. The setPaintTicks() method is invoked to cause the ticks to be displayed. The addChangeListener() method sets up an event handler for the slider.
The setOrientation(), setMinimum(), setMaximum(), and setValue() methods set up the progress bar's orientation, range, and initial value. The setBorderPainted() method controls the display of the progress bar's border. The slider, progress bar, and two labels are added to the Bars tab via the JPanel object referenced by barPanel.
The setupListPanel() method sets the cell height of the icon list to 123 pixels. (I arrived at this value through trial and error. It seemed to be the most pleasing height for the icons.) The list (referenced by the leafList variable) is then added to the tab.
The setupTablePanel() method sets up the JTable object's parameters and then adds the table to the Table tab. It sets the intercell spacing to a 20 pixel border. The sizeColumnsToFit() method causes table columns to be automatically resized to fit in the space allocated to the table.
The main() method simply creates a SwingStart object. The WindowHandler inner class handles the window closing event by exiting the JVM.
The SliderHandler class implements the ChangeListener interface of com.sun.java.swing.event. The stateChanged() method handles changes to the slider position by getting the value of the slider and setting the value of the progress bar to the slider value.
In this chapter, you were introduced to the GUI controls of Swing. You learned what Swing is, where it comes from, and its relationship to the AWT and the JFC as a whole. You learned about the Swing component hierarchy and about the Swing packages. You then developed an example Swing-based GUI. In the next chapter, you'll encounter more examples that will expand upon your Swing programming skills.
© Copyright 1998, Macmillan Computer Publishing. All rights reserved.