How to use Swing Java

how to use swing in java and how to import swing in java
JohenCorner Profile Pic
JohenCorner,France,Professional
Published Date:02-08-2017
Your Website URL(Optional)
Comment
Swing Swing is Java’s graphical user interface toolkit. The javax.swing package (and its nu‐ merous subpackages) contain classes representing interface items such as windows, buttons, combo boxes, trees, tables, and menus—everything you need to build a modern, rich client-side application. Swing is part of a larger collection of software called the Java Foundation Classes (JFC), which includes the following APIs: • The Abstract Window Toolkit (AWT), the original user interface toolkit and base graphics classes • Swing, the pure Java user interface toolkit • Accessibility, which provides tools for integrating nonstandard input and output devices into your user interfaces • The 2D API, a comprehensive set of classes for high-quality drawing • Drag and Drop, an API that supports the drag-and-drop metaphor JFC is one of the largest and most complex parts of the standard Java platform, so it shouldn’t be any surprise that we’ll take several chapters to discuss it. In fact, we won’t even get to talk about all of it, just the most important parts—Swing and the 2D API. Here’s the lay of the land: • This chapter covers the basic concepts you need to understand how to build user interfaces with Swing. • Chapter 17 discusses the basic components from which user interfaces are built: buttons, lists, text fields, checkboxes, and so on. • Chapter 18 dives further into the Swing toolkit, describing text components, trees, tables, and other advanced components. 589 a • Chapter 19 discusses layout managers, which are responsible for arranging com‐ ponents within a window. • Chapter 20 discusses the fundamentals of drawing, including simple image display. • Chapter 21 covers the image generation and processing tools of the java.awt.im age package. We’ll throw in audio and video for good measure. We can’t cover the full functionality of Swing in this book; if you want the whole story, see Java Swing by Marc Loy, Robert Eckstein, Dave Wood, Brian Cole, and James Elliott (O’Reilly). Instead, we’ll cover the basic tools you are most likely to use and show some examples of what can be done with some of the more advanced features. Figure 16-1 shows the user interface component classes of thejavax.swing package. To understand Swing, it helps to understand its predecessor, AWT. As its name suggests, AWT is an abstraction. Like the rest of Java, it was designed to be portable; its func‐ tionality is the same for all Java implementations. However, people generally expect their applications to have a consistent look and feel and that is usually different on different platforms. So AWT was designed to provide the same functionality on all platforms, yet have the appearance of a native application. The idea is that you could choose to write your code under Windows, then run it on an X Window System or a Macintosh and get more or less the native look and feel on each platform for free.To achieve platform binding, AWT uses interchangeable toolkits that interact with the host windowing sys‐ tem to display user interface components. This shields the Java application from the details of its environment in which it’s running and keeps the APIs pure. Let’s say you ask AWT to create a button. When your application or applet runs, a toolkit appropriate to the host environment renders the button appropriately: on Windows, you can get a button that looks like other Windows buttons; on a Macintosh, you can get a Mac button; and so on. AWT had some serious shortcomings, however. The worst was that the use of platform- specific toolkits meant that AWT applications might be subtly incompatible on different platforms. Furthermore, AWT lacked advanced user interface components, such as trees and grids, which were not common to all environments. AWT provided the desired look and feel, but limited the features and true portability of Java GUI applications. Swing takes a fundamentally different approach. Instead of using native toolkits to sup‐ ply interface items, such as buttons and combo boxes, components in Swing are im‐ plemented in Java itself. This means that, whatever platform you’re using, by default a Swing button (for example) looks the same. However, Swing also provides a powerful, pluggable look-and-feel API that allows the native operating system appearance to be rendered at the Java level. Working purely in Java makes Swing much less prone to platform-specific bugs, which were a problem for AWT. It also means that Swing com‐ ponents are much more flexible and can be extended and modified in your applications in ways that native components could never be. 590 Chapter 16: Swing aFigure 16-1. User interface components in the javax.swing package Working with user interface components in Swing is meant to be easy. When building a user interface for your application, you’ll be working with a large set of prefabricated components. It’s easy to assemble a collection of user interface components (buttons, text areas, etc.) and arrange them inside containers to build complex layouts. However, when necessary, you can build upon these simple components to make entirely new kinds of interface gadgets that are completely portable and reusable. Swing 591 a Swing uses layout managers to arrange components inside containers and control their sizing and positioning. Layout managers define a strategy for arranging components instead of specifying absolute positions. For example, you can define a user interface with a collection of buttons and text areas and be reasonably confident that it will always display correctly, even if the user resizes the application window. It doesn’t matter what platform or user interface look-and-feel you’re using; the layout manager should still position them sensibly with respect to each other. The next two chapters contain examples using most of the components in the jav ax.swing package. Before we dive into those examples, we need to spend some time talking about the concepts Swing uses for creating and handling user interfaces. This material should get you up to speed on GUI concepts and how they are used in Java. Components A component is the fundamental user interface object in Java. Everything you see on the display in a Java application is a component. This includes things like windows, panels, buttons, checkboxes, scrollbars, lists, menus, and text fields. To be used, a component usually must be placed in a container. Container objects group components, arrange them for display using a layout manager, and associate them with a particular display device. All Swing components are derived from the abstract javax.swing.JCompo nent class, as you saw in Figure 16-1. For example, the JButton class is a subclass of AbstractButton, which is itself a subclass of theJComponent class. JComponent is the root of the Swing component hierarchy, but it descends from the AWTContainer class. At this bottom level, Swing is based on AWT, so our conversation occasionally delves into the AWT package. Container’s superclass is Component, the root of all AWT components, and Component’s superclass is, finally, Object. Because JComponent inherits fromContainer, it has the capabilities of both a component and a container. AWT and Swing, then, have parallel hierarchies. The root of AWT’s hierarchy isCompo nent, while Swing’s components are based onJComponent. You’ll find similar classes in both hierarchies, such asButton andJButton,List, andJList. But Swing is much more than a replacement for AWT—it contains sophisticated components as well as a real implementation of the Model-View-Controller (MVC) paradigm, which we’ll discuss later. For the sake of simplicity, we can split the functionality of theJComponent class into two categories: appearance and behavior. TheJComponent class contains methods and vari‐ ables that control an object’s general appearance. This includes basic attributes, such as its visibility, its current size and location, and certain common graphical defaults, such as font and background color, used by different subclasses in different ways. The 592 Chapter 16: Swing a JComponent class also contains graphics and event-handling methods, which are over‐ ridden by subclasses to produce all of the different kinds of widgets that we will see. When a component is first displayed, it’s associated with a particular display device. The JComponent class encapsulates access to its display area on that device. It includes tools for rendering graphics, for working with off-screen resources, and for receiving user input. Under the covers, JComponent makes heavy use of the Java 2D API to handle things like font smoothing, rendering optimizations, and rendering hints. With recent versions of Java (6 and later), rendering speed and quality are often indistinguishable from native applications on popular operating systems. When we talk about a component’s behavior, we mean the way it responds to user-driven events. When the user performs an action (such as pressing the mouse button) within a component’s display area, a Swing thread delivers an event object that describes what happened. The event is delivered to objects that have registered themselves as listeners for that type of event from that component. For example, when the user clicks on a button, the button generates anActionEvent object. To receive those events, an object registers with the button as anActionListener. Events are delivered by invoking designated event handler methods within the receiving object (the “listener”). A listener object receives specific types of events through methods of its listener interfaces (for example, through the actionPerformed() method of the ActionListener interface) for the types of events in which it is interested. Specific types of events cover different categories of component user interaction. For example, MouseEvents describe activities of the mouse within a component’s area, KeyEvents describe keypresses, and higher-level events (such asActionEvents) indicate that a user interface component has done its job. We will describe events thoroughly in this chapter because they are so fundamental to the way in which user interfaces function in Java. But they aren’t limited to building user interfaces; they are an important interobject communications mechanism, which may be used by completely nongraphical parts of an application, as well. They are particularly important in the context of JavaBeans, which uses events as a generalized change- notification mechanism. Swing’s event architecture is very flexible. Instead of requiring every component to listen for and handle events for its own bit of the user interface, an application may register arbitrary event “handler” objects to receive the events for one or more components and “glue” those events to the correct application logic. A container might, for example, process some of the events relating to its child components. In the graphical realm, the primary responsibility of a container is to lay out the com‐ ponents it contains visually, within its borders. A component informs its container when it does something that might affect other components in the container, such as changing Components 593 a its size or visibility. The container then tells its layout manager that it is time to rearrange the child components. As we mentioned, Swing components are all fundamentally derived from Container. This doesn’t mean that all Swing components can meaningfully contain arbitrary GUI elements within themselves. It does mean that the container-component relationship is built in at a low level. Containers can manage and arrangeJComponent objects without knowing what they are or what they are doing. Components can be swapped and re‐ placed with new versions easily and combined into composite user interface objects that can be treated as individual components themselves. This lends itself well to building larger, reusable user interface items. Peers and Look-and-Feel Swing components are sometimes referred to as peerless, or lightweight. These terms refer to the relationship that AWT has (and Swing does not have, respectively) with the native toolkits for rendering components on each platform. To get native components on the screen, AWT utilizes a set of peer objects that bridge the gap from pure Java to the host operating system. At some level, of course, all our components have to talk to objects that contain native methods to interact with the host operating environment; the difference is at what level this occurs. AWT uses a set of peer interfaces. The peer interface makes it possible for a pure Java-language graphic component to use a corresponding real component—the peer object—in the native environment. With AWT, you don’t generally deal directly with peer interfaces or the objects behind them; peer handling is encapsulated within theComponent class. AWT relies heavily on peers. For example, if you create a window and add eight buttons to it, AWT creates nine peers for you—one for the window and one for each of the buttons. As an application programmer, you don’t have to worry about the peers, but they are always lurking under the surface, doing the real work of interacting with the operating system’s windowing toolkit. In Swing, by contrast, most components are peerless, or lightweight. This means that Swing components don’t have any direct interaction with the underlying windowing system. They draw themselves in their parent container and respond to user events in pure Java, with no native code involved. In Swing, only the top-level (lowest API level) windows interact with the windowing system. These Swing containers descend from AWT counterparts, and, thus, still have peers. In Swing, if you create a window and add eight buttons to it, only one peer is created—for the window. Because it has fewer in‐ teractions with the underlying windowing system than AWT, Swing is less vulnerable to the peculiarities of any particular platform. 594 Chapter 16: Swing aWith lightweight components, it is easy to change their appearance. Because each com‐ ponent draws itself instead of relying on a peer, it can decide at runtime how to render itself. Accordingly, Swing supports different look-and-feel schemes, which can be changed at runtime. (A look-and-feel is the collected appearance of components in an application.) Look-and-feels based on Windows, Macintosh, and Motif are available (though licensing issues may encumber their use on various platforms), as well as several entirely original Java creations, including Metal, Synth and Nimbus. Metal is the default cross-platform look-and-feel. It has a flat minimalist aesthetic and is very functional but, at this point, appears dated when compared to current versions of popular desktop environments. Synth makes Java applications “skinnable” at a high level using an XML descriptor file and images as resources. Java SE 6 update 10 introduced Nimbus, the first Java look-and-feel that is aesthetically on par with modern desktop operating sys‐ tems such as OS X and Windows. Nimbus is vector-based, which allows components to be smoothly scaled for use on the new generation of high-density displays. If you want a consistent cross-platform look-and-feel, Nimbus is the best option. The MVC Framework Before continuing our discussion of GUI concepts, we want to make a brief aside and talk about the MVC framework. As we’ve discussed, MVC is a method of building reusable components that logically separates the structure, presentation, and behavior of a component into separate pieces. MVC is primarily concerned with building user interface components, but the basic ideas can be applied to many design issues; its principles can be seen throughout Java. The fundamental idea behind MVC is the separation of the data model for an item from its presentation. For example, we can draw different representations of the data in a spreadsheet (e.g., bar graphs, pie charts). The data is the model; the particular repre‐ sentation is the view. A single model can have many views that present the data differ‐ ently. A user interface component’s controller defines and governs its behavior. Typically, this includes changes to the model, which, in turn, cause the view(s) to change. For a checkbox component, the data model could be a single Boolean variable, indicating whether it’s checked or not. The behavior for handling mouse-click events would alter the model, and the view would examine that data when it draws the on-screen representation. Components 595 aThe way in which Swing objects communicate, by passing events from sources to lis‐ teners, is part of this MVC concept of separation. Event listeners are “observers” (con‐ 1 trollers) and event sources are “observables” (models). When an observable changes or performs a function, it notifies all its observers of the activity. Swing components explicitly support MVC. Each component is actually composed of two pieces. One piece, called the UI-delegate, is responsible for the “view” and “con‐ troller” roles. It takes care of drawing the component and responding to user events. The second piece is the data model itself. This separation makes it possible for multiple Swing components to share a single data model. For example, a read-only text box and a drop-down list box could use the same list of strings as a data model. Painting In an event-driven environment such as Swing, components can be asked to draw themselves at any time. In a more procedural programming environment, you might expect a component to be involved in drawing only when first created or when it changes its appearance. In Java, however, components act in a way that is closely tied to the underlying behavior of the display environment. For example, when you obscure a component with another window and then reexpose it, a Swing thread may ask the component to redraw itself. Swing asks a component to draw itself by calling its paint() method.paint() may be called at any time, but in practice, it’s called when the object is first made visible, when‐ ever it changes its appearance, or whenever some tragedy in the display system messes up its area. Because paint() can’t generally make any assumptions about why it was called, it must redraw the component’s entire display. The system may limit the drawing if only part of the component needs to be redrawn, but you don’t have to worry about this. Swing is fairly smart and will do everything it can to avoid asking components to redraw themselves (including using “backing store” where applicable). A component never calls itspaint() method directly. Instead, if a component requires redrawing, it requests a call topaint() by invokingrepaint(). Therepaint() method asks Swing to schedule the component for repainting. At some point after that, a call to paint() occurs. Swing is allowed to manage these requests in whatever way is most efficient. If there are too many requests to handle, or if there are multiple requests for the same component, the thread can collapse a number of repaint requests into a single call topaint(). This means that you don’t normally know exactly whenpaint() is called in response to arepaint(); all you can expect is that it happens at least once, after you request it. 1. In Chapter 11, we described theObserver class andObservable interface of thejava.util package. Swing doesn’t use these classes directly, but it does use exactly the same design pattern for handling event sources and listeners. 596 Chapter 16: Swing a Calling repaint() is normally an implicit request to be updated as soon as possible. Another form ofrepaint() allows you to specify a time period within which you would like an update, giving the system more flexibility in scheduling the request. The system tries to repaint the component within the time you specify, but if you happen to make more than one repaint request within that time period, the system may simply condense them to carry out a single update within the time you specified. An application per‐ forming simple animation could use this method to govern its refresh rate (by specifying a period that is the inverse of the desired frame rate). As we’ve mentioned, Swing components can act as containers holding other compo‐ nents. Because every Swing component does its own drawing, Swing components are responsible for telling any contained components to draw themselves. Fortunately, this is all taken care of for you by a component’s default paint() method. If you override this method, however, you have to make sure to call the superclass’s implementation like this: public void paint(Graphics g) super.paint(g); ... There’s a cleaner way around this problem. All Swing components have a method called paintComponent(). While paint() is responsible for drawing the component as well as its contained components, paintComponent()’s sole responsibility is drawing the component itself. If you overridepaintComponent() instead ofpaint(), you won’t have to worry about drawing contained components. Bothpaint() andpaintComponent() receive a single argument: aGraphics object. The Graphics object represents the component’s graphics context. It corresponds to the area of the screen on which the component can draw and provides the methods for per‐ forming primitive drawing and image manipulation. (We’ll look at the Graphics class in detail in Chapter 18.) Enabling and Disabling Components Standard Swing components can be turned on and off by calling the setEnabled() method. When a component such as a JButton or JTextField is disabled, it becomes “ghosted” or “greyed out” and doesn’t respond to user input. For example, let’s see how to create a component that can be used only once. This re‐ quires getting ahead of the story; we won’t explain some aspects of this example until later. Earlier, we said that aJButton generates anActionEvent when it is pressed. This event is delivered to the listeners’actionPerformed() method. The following code dis‐ ables the component that generated the event: Components 597 a public boolean void actionPerformed(ActionEvent e ) ((JComponent)e.getSource()).setEnabled(false); This code callsgetSource() to find out which component generated the event. We cast the result to JComponent because we don’t necessarily know what kind of component we’re dealing with; it might not be a button, because other kinds of components can generate action events. Once we know which component generated the event, we disable it. You can also disable an entire container. Disabling a JPanel, for instance, disables all the components it contains. Focus, Please In order to receive keyboard events, a component has to have keyboard focus. The component with the focus is the currently selected component on the screen and is usually highlighted visually. It receives all keyboard event information until the focus changes to a new component. Typically, a component receives focus when the user clicks on it with the mouse or navigates to it using the keyboard. A component can ask for focus with the JComponent ’s requestFocus() method. You can configure whether a given component is eligible to receive focus with the setFocusable() method. By de‐ fault, most components, including things such as buttons and checkboxes, are “focus‐ able.” To make an entire window and its components nonfocusable, use the Window setFocusableWindowState() method. The control of focus is often at the heart of the user’s experience with an application. Especially with text entry fields and forms, users are accustomed to a smooth transfer of focus with the use of keyboard navigation cues (e.g., Tab and Shift-Tab for forward and backward field navigation). The management of focus in a large GUI with many components could be complex. Fortunately, in Java 1.4 and later, Swing handles almost all this behavior for you, so, in general, you don’t have to implement code to specify how focus is transferred. Java 1.4 introduced an entirely new focus subsystem. The flexible KeyboardFocusManager API provides the expected common behavior by default and allows customization via FocusTraversalPolicy objects. We’ll discuss focus-related events later in this chapter and focus navigation more in Chapter 18. Other Component Methods TheJComponent class is very large; it has to provide the base-level functionality for all the various kinds of Java GUI objects. It inherits a lot of functionality from its parent Container and Component classes. We don’t have room to document every method of the JComponent class here, but we’ll flesh out our discussion by covering some of the more important ones: 598 Chapter 16: Swing aContainer getParent() String getName() void setName(String name) Get or assign the String name of this component. Naming a component is useful for debugging. The name is returned bytoString(). void setVisible(boolean visible) Make the component visible or invisible within its container. If you change the component’s visibility, the container’s layout manager automatically lays out its visible components. Color getForeground() void setForeground(Color c) void setBackground(Color c) Color getBackground() Get and set the foreground and background colors for this component. The fore‐ ground color of any component is the default color used for drawing. For example, it is the color used for text in a text field as well as the default drawing color for the Graphics object passed to the component’spaint() andpaintComponent() meth‐ ods. The background color is used to fill the component’s area when it is cleared by the default implementation ofupdate(). Dimension getSize() void setSize(int width, int height) Get and set the current size of the component. Note that a layout manager may change the size of a component even after you’ve set its size yourself. To change the size a component “wants” to be, usesetPreferredSize(). There are other methods inJComponent to set its location, but this is normally the job of a layout manager. Dimension getPreferredSize() void setPreferredSize(Dimension preferredSize) Use these methods to examine or set the preferred size of a component. Layout managers attempt to set components to their preferred sizes. If you change a com‐ ponent’s preferred size, you must call the methodrevalidate() on the component to get it laid out again. Cursor getCursor() void setCursor(Cursor cursor) Get or set the type of cursor (mouse pointer) used when the mouse is over this component’s area. For example: JComponent myComponent = ...; Cursor crossHairs = Cursor.getPredefinedCursor( Cursor.CROSSHAIR_CURSOR ); myComponent.setCursor( crossHairs ); Components 599 aContainers A container is a kind of component that holds and manages other components. Three of the most useful general container types areJFrame,JPanel, andJApplet. AJFrame is a top-level window on your display.JFrame is derived fromjava.awt.Window, which is pretty much the same but lacks a border (JWindow is the swing version ofWindow). A JPanel is a generic container element that groups components insideJFrames and other JPanels. TheJApplet class is a kind of container that provides the foundation for applets that run inside web browsers. Like other containers, a JApplet can hold other user- interface components. You can also use theJComponent class directly, like aJPanel, to hold components inside another container. With the exception of JFrame, JWindow, JApplet, andJDialog (another window-like container), which are derived from AWT components, all the components and containers in Swing are lightweight. A container maintains the list of “child” components it manages and has methods for dealing with those components. Note that this child relationship refers to a visual hierarchy, not a subclass/superclass hierarchy. By themselves, most components aren’t very useful until they are added to a container and displayed. Theadd() method of the Container class adds a component to the container. Thereafter, this component can be displayed in the container’s display area and positioned by its layout manager. You can remove a component from a container with theremove() method. Layout Managers A layout manager is an object that controls the placement and sizing of components within the display area of a container. A layout manager is like a window manager in a display system; it controls where the components go and how big they are. Every con‐ tainer has a default layout manager, but you can install a new one by calling the con‐ tainer’ssetLayout() method. Swing comes with a few layout managers that implement common layout schemes. The default layout manager for aJPanel is aFlowLayout, which tries to place objects at their preferred size from left to right and top to bottom in the container. The default for a JFrame is aBorderLayout, which places objects at specific locations within the window, such as NORTH, SOUTH, and CENTER. Another layout manager, GridLayout, arranges components in a rectangular grid. The most general (and difficult to use) layout manager isGridBagLayout, which lets you do the kinds of things you can do with HTML tables. (We’ll get into the details of all these layout managers in Chapter 19.) When you add a component to a container using a simple layout manager, you’ll often use the version ofadd() that takes a singleComponent as an argument. However, if you’re using a layout manager that uses “constraints,” such as BorderLayout or GridBagLay out, you must specify additional information about where to put the new component. For that, you can use the version that takes a constraint object. Here’s how to place a component at the top edge of a container that uses aBorderLayout manager: 600 Chapter 16: Swing a myContainer.add(myComponent, BorderLayout.NORTH); In this case, the constraint object is the static member variable NORTH. GridBagLayout uses a much more complex constraint object to specify positioning. Insets Insets specify a container’s margins; the space specified by the container’s insets won’t be used by a layout manager. Insets are described by anInsets object, which has four publicint fields:top,bottom,left, andright. You normally don’t need to worry about the insets; the container sets them automatically, taking into account extras like the menu bar that may appear at the top of a frame. To find the insets, call the component’s getInsets() method, which returns anInsets object. Z-Ordering (Stacking Components) With the standard layout managers, components are not allowed to overlap. However, if you use custom-built layout managers or absolute positioning, components within a container may overlap. If they do, the order in which components were added to a container matters. When components overlap, they are “stacked” in the order in which they were added: the first component added to the container is on top, and the last is on the bottom. To give you more control over stacking, two additional forms of the add() method take an extra integer argument that lets you specify the component’s exact position in the container’s stacking order. Again, you don’t normally need to think about this, but it’s nice to know for the sake of completeness that it’s there. The revalidate() and doLayout() Methods A layout manager arranges the components in a container only when it is asked to do so. Several things can mess up a container after it’s initially laid out: • Changing its size • Resizing or moving one of its child components • Adding, showing, removing, or hiding a child component Any of these actions cause the container to be marked invalid. This means that it needs to have its child components readjusted by its layout manager. In most cases, Swing readjusts the layout automatically. All components, not just containers, maintain a no‐ tion of when they are valid or invalid. If the size, location, or internal layout of a Swing component changes, its revalidate() method is automatically called. Internally, the revalidate() method first calls the methodinvalidate() to mark the component and all its enclosing containers as invalid. It then validates the tree. Validation descends the hierarchy, starting at the nearest validation root container, recursively validating each child. Validating a childContainer means invoking itsdoLayout() method, which asks Components 601 a the layout manager to do its job and then notes that theContainer has been reorganized by setting its state to valid again. A validation root is a container that can accommodate children of any size such as JScrollPane (and, hence, can accommodate any possible changes in its child hierarchy without upsetting its own parents). There are a few cases in which you may need to tell Swing to fix things manually. One example is when you change the preferred size of a component (as opposed to its actual onscreen size). To clean up the layout, call the revalidate() method. For example, if you have a small JPanel—say, a keypad holding some buttons—and you change the preferred size of theJPanel by calling itssetPreferredSize() method, you should also callrevalidate() on the panel or its immediate container. The layout manager of the panel then rearranges its buttons to fit inside its new area. Managing Components There are a few additional tools of theContainer class we should mention: Component getComponents() Returns the container’s components in an array. void list(PrintWriter out, int indent) Generates a list of the components in this container and writes them to the specified PrintWriter. Component getComponentAt(int x, int y) Tells you what component is at the specified coordinates in the container’s coordi‐ nate system. Listening for Components You can use theContainerListener interface to automate setting up a container’s new components. A container that implements this interface can receive an event whenever it gains or loses a component. This facility makes it easy for a container to micromanage its components. Windows, Frames and Splash Screens Windows and frames are the top-level containers for Java components. A JWindow is simply a plain, graphical screen that displays in your windowing system. Windows have no frills; they are mainly suitable for pop-up windows and in situations where drop- down components such as menus and combo boxes extend outside their parent frame. JFrame, on the other hand, is a subclass ofJWindow that has a titlebar, window-managed buttons (close, minimize, etc.), and border. You can drag a frame around on the screen and resize it, using the ordinary controls for your windowing environment. Figure 16-2 shows aJFrame on the left and aJWindow on the right. 602 Chapter 16: Swing a All other Swing components and containers must be held, at some level, inside aJWind ow orJFrame. Applets are a kind ofContainer. Even applets must be housed in a frame or window, though normally you don’t see an applet’s parent frame because it is part of (or simply is) the browser orappletviewer displaying the applet. Figure 16-2. A frame and a window JFrames and JWindows are the only components that can be displayed without being added or attached to another Container. After creating a JFrame or JWindow, you can call the setVisible() method to display it. The following short application creates a JFrame and aJWindow and displays them side by side, just as in Figure 16-2. //file: TopLevelWindows.java import javax.swing.; public class TopLevelWindows public static void main(String args) JFrame frame = new JFrame("The Frame"); frame.setSize(300, 300); frame.setLocation(100, 100); JWindow window = new JWindow(); window.setSize(300, 300); window.setLocation(500, 100); frame.setVisible(true); window.setVisible(true); The JFrame constructor can take a String argument that supplies a title, displayed in theJFrame’s titlebar. (Or you can create theJFrame with no title and callsetTitle() to supply the title later.) The JFrame’s size and location on your desktop are determined by the calls to setSize() and setLocation(). After creating the JFrame, we create a Components 603 a JWindow in almost exactly the same way. The JWindow doesn’t have a titlebar, so there are no arguments to theJWindow constructor. Once theJFrame andJWindow are set up, we callsetVisible(true) to get them on the screen. ThesetVisible() method returns immediately, without blocking. Fortunately, our application does not exit, even though we’ve reached the end of themain() method, because the windows are still visible. You can close theJFrame by clicking on the close button in the titlebar. JFrame’s default behavior is to hide itself when you click on the box by calling setVisible(false). You can alter this behavior by calling the setDe faultCloseOperation() method or by adding an event listener, which we’ll cover later. Because we haven’t arranged any other means here, you will need to hit Ctrl-C or what‐ ever keystroke kills a process on your machine in order to stop execution of theTopLe velWindows application. Use of aSplashScreen, which is an AWT class used to control a specialized container, is the preferred way to display a start-up screen for Swing applications. Prior to Java 1.6, applications were forced to use Window or JWindow for this purpose, but these are suboptimal solutions for a splash screen because they are only displayed after the JVM, AWT, and Swing libraries are initialized. The new splash screen object allows you to specify an image file in your application jar’s manifest (see Chapter 3) that will be dis‐ played immediately after launch without having to wait for the JVM to initialize. Spec‐ ifying a splash screen image in your jar manifest is trivial. Manifest-Version: 1.0 Main-Class: MangoMango1 SplashScreen-Image: ripe_mango.png No code is required to display a splash screen. The ripe_mango.png image will appear centered on the screen until the first AWT or Swing window is shown by the Mango‐ Mango1 application. Supported image types are GIF, JPEG, and PNG. Other Methods for Controlling Frames The setLocation() method of the Component class can be used on a JFrame or JWind ow to set its position on the screen. The x and y coordinates are relative to the screen’s origin (the top-left corner). You can use thetoFront() andtoBack() methods to place aJFrame orJWindow in front of, or behind, other windows. By default, a user is allowed to resize a JFrame, but you can prevent resizing by callingsetResizable(false) before showing theJFrame. On most systems, frames can be “iconified”—that is, they can be shrunk down and represented by a little icon image. You can get and set a frame’s icon image by calling getIconImage() andsetIconImage(). As you can with all components, you can set the cursor by calling thesetCursor() method. 604 Chapter 16: Swing aContent Panes Windows and frames have a little more structure than simple containers. Specifically, to support some of the fancier GUI features that require overlaying graphics (such as pop ups and menus), windows and frames actually consist of a number of separate overlapping container “panes” (as in glass) with names such as the root pane, layered pane, and glass pane. The primary pane of interest is usually the content pane. The content pane is just aContainer that covers the visible area of theJFrame orJWindow; it is the container to which we want to add child components. For convenience, JFrame and JWindow delegate methods such as add() and setLay out() to theirContentPane. In other words, callingmyFrame.add(component) is equiv‐ alent to callingmyFrame.getContentPane().add(component). //file: MangoMango1.java import java.awt.; import javax.swing.; public class MangoMango1 public static void main(String args) JFrame frame = new JFrame("The Frame"); // The three methods below are delegated to the frame's ContentPane. frame.setLayout(new FlowLayout()); frame.add(new JLabel("Mango")); frame.add(new JButton("Mango")); frame.setLocation(100, 100); frame.pack(); frame.setVisible(true); The call toJFrame’spack() method tells the frame window to resize itself to the mini‐ mum size required to hold all its components. Instead of having to determine the size of theJFrame,pack tells it to be “just big enough.” If you do want to set the absolute size of theJFrame yourself, callsetSize() instead. We’ll cover labels and buttons in Chapter 17 and layouts in Chapter 19. Desktop Integration One of the focuses of Java 6 was improving desktop integration so that Swing apps can stand toe-to-toe with native apps. The new desktop features provide access to the system tray, browser, email client and file/application associations. TheDesktop class injava.awt provides the ability to: • Navigate to a URI with the default browser • Launch the default mail client and populate the “To:” field Components 605 a • Open, edit, or print a file utilizing its associated application The Desktop class has a very simple API. The following example opens the default browser and navigates to the Duke Lemur Center’s home page. //file: DisplayLemur.java import java.awt.; import java.io.; import java.net.; public class DisplayLemur public static void main(String args) URI uri = null; try uri = new URI("http://lemur.duke.edu"); Desktop.getDesktop().browse(uri); catch(IOException ioe) System.out.println("Cannot browse to " + uri); catch(URISyntaxException use) System.out.println("The URI " + uri + " is malformed"); All the aforementioned desktop features are similarly available as single method calls on the Desktop singleton: open(File file), edit(File file), print(File file), andmail(URI mailtoURI). TheSystemTray class, also found injava.awt, provides access to the area of the desktop that allows menu items to perform actions on currently running programs. On Win‐ dows, this is the Taskbar Status Area. On OS X, it’s the Menu Extras area on the right of the system menu. On GNOME, it’s the Notification Area. The following example creates a TrayIcon, places it in the SystemTray, and attaches a single menu item. Selecting the menu item will cause a greeting dialog to appear. import java.awt.; import java.awt.event.; import java.awt.image.; import javax.swing.; public class AlohaTray public static void main(String args) throws AWTException MenuItem greetItem = new MenuItem("Greet me"); // Listen for a menu selection and display a greeting dialog greetItem.addActionListener(new ActionListener() public void actionPerformed(ActionEvent e) JOptionPane.showMessageDialog(null, "Aloha"); System.exit(0); 606 Chapter 16: Swing a ); // Create the TrayIcon's PopupMenu and add the MenuItem PopupMenu popup = new PopupMenu(); popup.add(greetItem); // Create the TrayIcon and add it to the SystemTray TrayIcon trayIcon = new TrayIcon(getIconImage(), "A friendly greeting", popup); SystemTray.getSystemTray().add(trayIcon); // Grabbing a default Swing icon for the SystemTray private static Image getIconImage() Icon icon = UIManager.getIcon("OptionPane.informationIcon"); BufferedImage image = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB); icon.paintIcon(null, image.getGraphics(), 0, 0); return image; Events We’ve spent a lot of time discussing the different kinds of objects in Swing—components, containers, and special containers such as frames and windows. Now it’s time to discuss interobject communication in detail. Swing objects communicate by sending events. The way we talk about events—“firing” them and “handling” them—makes it sound as if they are part of some special Java language feature. But they aren’t. An event is simply an ordinary Java object that is delivered to its receiver by invoking an ordinary Java method. Everything else, however interesting, is purely convention. The entire Java event mechanism is really just a set of conventions for the kinds of descriptive objects that should be delivered; these conven‐ tions prescribe when, how, and to whom events should be delivered. Events are sent from a single source object to one or more listeners. A listener imple‐ ments prescribed event-handling methods that enable it to receive a type of event. It then registers itself with a source of that kind of event. Sometimes an adapter object may be interposed between the event source and the listener, but in any case, registration of a listener is always established before any events are delivered. An event object is an instance of a subclass ofjava.util.EventObject; it holds infor‐ mation about something that’s happened to its source. The EventObject parent class itself serves mainly to identify event objects; the only information it contains is a ref‐ erence to the event source (the object that sent the event). Components don’t normally send or receive EventObjects as such; they work with subclasses that provide more specific information. Events 607 a AWTEvent is a subclass of java.awt.EventObject; further subclasses of AWTEvent pro‐ vide information about specific event types. Swing has events of its own that descend directly fromEventObject. For the most part, you’ll just be working with specific event subclasses from the AWT or Swing packages. ActionEvents correspond to a decisive “action” that a user has taken with the compo‐ nent, such as clicking a button or pressing Enter. AnActionEvent carries the name of an action to be performed (the action command) by the program. MouseEvents are generated when a user uses the mouse within a component’s area. They describe the state of the mouse and therefore carry such information as thex andy coordinates and the state of your mouse buttons at the time theMouseEvent was created. ActionEvent operates at a higher semantic level thanMouseEvent: anActionEvent lets us know that a component has performed its job; aMouseEvent simply confers a lot of information about the mouse at a given time. You could figure out that somebody clicked on aJButton by examining mouse events, but it is simpler to work with action events. The precise meaning of an event can also depend on the context in which it is received. Event Receivers and Listener Interfaces An event is delivered by passing it as an argument to the receiving object’s event handler method. ActionEvents, for example, are always delivered to a method called action Performed() in the receiver: public void actionPerformed( ActionEvent e ) ... For each type of event, a corresponding listener interface prescribes the method(s) it must provide to receive those events. In this case, any object that receives ActionEvents must implement theActionListener interface: public interface ActionListener extends java.util.EventListener public void actionPerformed( ActionEvent e ); All listener interfaces are subinterfaces ofjava.util.EventListener, which is an emp‐ ty interface. It exists only to help Java-based tools such as IDEs identify listener interfaces. Listener interfaces are required for a number of reasons. First, they help to identify objects that can receive a given type of event—they make event hookups “strongly typed.” Event listener interfaces allow us to give the event handler methods friendly, descriptive names and still make it easy for documentation, tools, and humans to rec‐ ognize them in a class. Next, listener interfaces are useful because several methods can be specified for an event receiver. For example, the FocusListener interface contains two methods: 608 Chapter 16: Swing a