Thursday, June 7, 2012

GIST NOTES 21 - Swing

GIST NOTES 21 - Swing

[DISCLAIMER: This is solely for non-commercial use. I don't claim ownership of this content. This is a crux of all my readings studies and analysis. Some of them are excerpts from famous books/sources on  the subject. Some of them are my contemplation upon experiments with direct hand coded code samples using IDE or notepad.

I've created this mainly to reduce an entire book into few pages of critical content that we should never forget. Even after years, you don't need to read the entire book again to get back its philosophy. I hope these notes will help you to replay the entire book in your mind once again.]

Note - This one is incomplete at the moment

Web Clients: complete-send-process-return-display application model.
Rich Clients: very “rich” user experience, taking advantage of
native facilities of the user’s desktop computer, such as graphics hardware
acceleration, to provide a more robust and full-featured application experience
than is provided by Web clients. Rich client applications can sometimes
take longer to start up than a simple Web page because there is more going
on in the application, and the GUIs tend to be more involved than Web GUIs
because there is more happening in the application than in simple Weboriented
applications. The interaction model is quite different because much
of the logic of the application is local, even if the application is talking to a
server on the back end.

New Model: AJAX - Lately, a new model has emerged for Web clients, called Asynchronous Java-
Script and XML (AJAX), where much of the client-server interaction can be
handled in parallel with the user’s interacting with each Web page. This transparent
client-server interaction can allow for dynamically updated Web pages
instead of the more tedious complete-send-process-return-display model of traditional
Web client applications. However, this model is still limited by the
browser container in which the application lives and by many of the constraints
that that browser model places on the application, including the extent to which
JavaScript features are supported, the security model of the browser, and the
physical GUI of the browser container around the application.

>AWT was the only GUI toolkit shipped with JDK 1.0 and still available as it is
>AWT builds on top of platform windows
>AWT has become an essential infrastructure piece that Swing depends on
>Swing provides more flexible and powerful GUI development environment than AWT
>AWT provides windowing, event mechanism, cut and paste, drag and drop, key board focus management, and input management
>AWT and Java 2D sit on Java Runtime; both are independent components; Swing sits on top of both AWT and Java 2D
>Java 2D: Is the graphics library of java
>AWT just provides basic drawing capabilities; Java 2D provides covers basics, broad set of drawing operations, advanced drawing operations, image manipulation, text and printing
>Swing uses Java 2D to render itself
>Both Java 2D and Swing were introduced in JDK 1.2
>Swing is a lightweight toolkit; except for toplevel windows all swing components are drawn using Java 2D and they do not correspond to native components as the case of AWT components
>AWT and Java 2D underlie Swing

• Events: The way that Swing receives and processes events is key to understanding
how threads interact within Swing and how your application
threads interact with Swing and AWT events.
• Painting: Swing painting is the process by which Swing manages application
and system requests to update the display.
• Rendering: Swing rendering is the process by which Swing calls its own
internal code as well as your application code in order to render components’
• Double-Buffering: Swing uses a back buffer to ensure smooth updates to
the screen.
• Threading: The Event mechanism is explored in more detail, and ways of
interacting effectively with the Swing GUI thread are examined.

>Painting vs Rendering : You render GUI before you paint it on a graphics device

>Events can come from native system(window becoming visible, keyboard input, etc) or from java itself(application spawned requests)
>All events are queued; java.awt.EventQueue object is responsible for dispatching these events; a single thread called EDT(event dispatch thread) serves all these events
>Painting process, system events related to GUI, application tasks modifying the GUI are all processed by EDT

Swing Painting
>Painting in Swing is the process by which your application updates the display.
>The process consists of a paint request being posted onto the event queue and results in calls to the paint() and paintComponent() methods on the EDT for each Swing component affected.
>Painting requests originate in one of two ways: The Swing or AWT libraries
themselves may post a repaint request, or the application code may post such a
request. Swing and AWT request a repaint in response to some event in the
native system or the GUI components. For example, when an application window
first appears on the screen, or when it is resized or exposed on the screen,
AWT receives a native expose event and issues a Java event to have the window
paint itself. Similarly, when the state of a component changes, such as when a
button is pressed, Swing issues a paint request to make sure that the button is
displayed in a pressed state. Applications can also issue a paint request to
Swing directly; this type of request is done in situations in which the application
code may know, on the basis of changes in some internal state, that the display
should change.
>In general, painting happens automatically; Swing detects when a component’s
contents have been altered such that the component needs to be repainted. Your
application does not normally need to issue paint requests to Swing unless it
knows that there has been some change to the display state that would not automatically
trigger a repaint. For example, if you change the text in a JLabel component,
Swing knows to repaint that label with the new text. But if your
application has detected a change to some internal variable, such as a variable
that affects the translucency of a component, then it might need to tell Swing that
a paint should be performed.
There are a handful of methods in components that are used to initiate painting.
These methods fall into two main categories: asynchronous requests and synchronous

Asynchronous Repaint Requests
These requests work by telling Swing what needs to be updated and letting
Swing handle the details of scheduling those requests and combining the requests
as appropriate.1 All of the asynchronous requests are variants of the repaint()
method. There are several of these methods, but they basically come in two flavors:
those that request the entire component be updated and those that specify
an area that needs to be updated.

1.Component.repaint() ---- repaints the entire component and its children
2.Component.repaint(int x, int y, int width, int height) ---- repaints only the specified region

#The simpler repaint() method is equivalent to calling repaint(0, 0, getWidth(), getHeight()).
#Asynchronous repaint requests are coalesced; requests are combined to remove redundant requests

Synchronous Paint Requests
>to invoke synchronous paint requests, you must be on EDT
>paint requests are not queued, by served right away
>paint requests are not coalesced as in the case of asynchronous requests one of JComponent.paintImmediately(int x, int y, int w, int h) or
JComponent.paintImmediately(Rectangle r) methods to paint synchronously

paintImmediately() is the only method that you should need to
call to force a synchronous paint of a component’s contents. This method tells
the component that the specified area must be updated; Swing calls paint()
internally on all of the appropriate components to make this happen. Component.paint(Graphics) method

Swing Rendering
>Swing painting: Repaint request is handled by the RepaintManager, which
calls paint() on the component, which then renders its content, its border, and its children.
>The Swing rendering model is straightforward and centers on Swing’s singlethreaded
painting model. First, the paint request is placed onto the event queue,
as described previously. Sometime later, on the EDT, the event is dispatched to
the Swing RepaintManager object, which calls paint() on the appropriate
component. That paint call results in a component painting first its own content,
then its border, and finally any components that it contains (which are called its
>In this way, an entire hierarchy of components, from the JFrame down to the
lowliest button, gets rendered. Note that this is a back-to-front method of painting,
where the backmost content (starting with the JFrame itself) gets rendered,then the items in that component, then the items in that component, and so on, until the frontmost components get displayed.

From Back to Front Painting: In graphics, this method is known as the painter’s algorithm, where a scene, like that in an oil painting,
is rendered from back to front, with the objects in front covering the objects in the background.
Of course, this method doesn’t apply to all paintings. Watercolors, for example, do not work well
with this algorithm because all of the colors blend together instead of covering (the Swing equivalent
would be if all components were translucent). And many modern paintings, such as those by
Jackson Pollock, appear to use algorithms that are more reminiscent of rendering artifacts.

The trick is figuring out where your application needs to plug into this system in
order to get the right stuff painted at the right time. There are three things that
your application should be concerned about:

• JComponent.paintComponent(Graphics): Applications that have components
with any custom rendering, such as Filthy Rich Clients, may need
to override this method to perform that custom rendering. This rendering
might include drawing graphics inside a canvas, but it also includes doing
anything custom to a standard component, such as rendering a gradient for
the background of a button. Standard Swing components already handle
this functionality for their graphics, so it is only for the case of custom components
with specialized rendering that this method must be overridden.
• Component.paint(Graphics): For the most part, Swing applications do
not override paint() directly, unlike older AWT applications. However,
there are important situations for Filthy Rich Clients when overriding
paint() is crucial because by doing so we can set up the graphics state that
will be used by a component and its children.
• JComponent.setOpaque(boolean): Applications may need to call
setOpaque(false) on a component depending on whether the component’s
rectangular bounds are not completely opaque. This action ensures
that Swing does the right thing for nonopaque components by rendering
contents behind the component appropriately. Note that all Swing components
except for JLabel are opaque by default.

public class OvalComponent extends JComponent {
public void paintComponent(Graphics g) {
g.fillRect(0, 0, getWidth(), getHeight());
g.fillOval(0, 0, getWidth(), getHeight());

Overriding paint() is not necessary in many Swing applications. In fact, overriding
paint() is not really recommended practice in general for Swing applications.
This recommendation is in contrast to older AWT applications, where
overriding paint() was equivalent to overriding paintComponent() in Swing;
this is how applications got custom rendering behavior in some components of
their applications. In Swing, however, the paint() method in JComponent,
which is the superclass for all Swing components, handles everything that any
rendering Swing component would typically want. JComponent’s paint()
method handles painting the content, borders, and children of any Swing component.
Swing’s painting model also handles double-buffering, which we read
more about shortly. It is the ability of JComponent to handle all of this functionality for paint() that
makes overriding paint() not recommended in general; subclasses may neglect
to do something (like drawing borders or painting children) that they should do.
It is far better to just let JComponent handle these details instead. But sometimes
overriding paint() is useful and necessary.

Tip: There is one important case in which it is useful for custom Swing components
to override paint(): when an application wants to alter the graphics state for all of
that component’s rendering.
A good example of this situation is a translucent component, where the user will
see through the component to items that lie behind it in the GUI. If you want a
Swing component, including its children and borders, to be completely translucent,
then you must change the Composite attribute of the Graphics object passed
into the paint() method. You could, of course, change the Graphics object
passed into paintComponent(), but that would alter the rendering only for that
component’s contents. JComponent creates a new Graphics object for each call to
paintComponent(), so altering the state of that Graphics object will affect only
the contents of that single component. What you should do instead is alter the
Graphics object that the contents, the borders, and the children are rendered with.
In this case, you should alter the Graphics object passed to the paint() method.

>JButton.setHorizontalAlignment()/JButton.setVerticalAlignment() position both icon and text inside the button
>JButton.setHorizontalTextPosition()/JButton.setVerticalTextPosition() position the text relative to the icon

>If the possible values of a formatted text field have an obvious order, use a spinner instead. A spinner uses a formatted text field by default, but adds two buttons that enable the user to choose a value in a sequence.

>Another alternative or adjunct to using a formatted text field is installing an input verifier on the field. A component's input verifier is called when the component nearly loses the keyboard focus. The input verifier enables you to check whether the value of the component is valid and optionally change it or stop the focus from being transferred.

>Creating your own component, or extending an existing one, requires a deeper understanding of Swing. This includes a firm understanding of Swing architecture, events, and lower-level classes. Also, if you decide to subclass a Swing component, the responsibilities of that component must be adopted and handled accordingly—otherwise, your new component may perform erratically.

Finally, you may wish to change the L&F of one or more Swing components. This is arguably the most complex of the three routes that you can take—it requires a thorough knowledge of the design, architectural fundamentals, and graphical primitives of each lightweight component. In addition, you need to understand how Swing's UIManager and UIDefaults classes work together to "set" each component's L&F.

>plaf=pluggable look and feel

>Swing actually uses a simplified variant of the MVC design called the model-delegate. This design combines the view and the controller object into a single element, the UI delegate, which draws the component to the screen and handles GUI events. Bundling graphics capabilities and event handling is somewhat easy in Java, since much of the event handling is taken care of in AWT. As you might expect, the communication between the model and the UI delegate then becomes a two-way street

The Z-Order Caveat: Lightweight and Heavyweight Components
> Because of z-order, it is not advisable to mix lightweight and heavyweight components in Swing.
>heavyweight components(JApplet, JFrame, JDialog, and JWindow) are always "opaque"—they have a rectangular shape and are nontransparent. This is because the host operating system typically allocates the entire painting region to the component, clearing it first.
>The remaining components are lightweight. So here is the crux of the dilemma: when a lightweight component is placed inside a heavyweight container, it shares (and actually borrows) the graphics context of the heavyweight component. The lightweight component must always draw itself on the same plane as the heavyweight component that contains it; as a result, it shares the z-order of the heavyweight component. In addition, lightweight components are bound to the clipping region of the top-level window or dialog that contains them. In effect, lightweight components are all "drawings" on the canvas of a heavyweight component. The drawings cannot go beyond the boundaries of the canvas and can always be covered by another canvas. Heavyweight components, however, are free from this restriction. Therefore, they always appear on top of the lightweight components — whether that is the intent or not.
>Heavyweight components have other ramifications in Swing as well. They do not work well in scrollpanes, where they can extend beyond the clipping boundaries; they also don't work in front of lightweight menus and menu bars (unless certain precautions are taken) or inside internal frames. Some Swing classes, however, offer an interesting approach to this problem. These classes allow you to specify whether the component draws itself using a lightweight or a heavyweight window. Hence, with a bit of judicious programming, you can keep your components correctly rendered—no matter where they are located.

Understanding Actions
Actions are a popular addition to Swing. An action allows a programmer to bundle a commonly used procedure and its bound properties (such as its name and an image to represent it) into a single class. This construct comes in handy if an application needs to call upon a particular function from multiple sources. For example, let's say that a Swing programmer creates an action that saves data to disk. The application could then invoke this action from both the Save menu item on the File menu and the Save button on a toolbar. Both components reference the same action object, which saves the data. If the Save function is disabled for some reason, this property can be set in the action as well. The menu and toolbar objects are automatically notified that they can no longer save any data, and they can relay that information to the user.

3.1.1 Actions and Containers
Swing containers, such as JMenu, JPopupMenu, and JToolBar, can each accept action objects with their add( ) methods. When an action is added, these containers automatically create a GUI component, which the add( ) method then returns to you for customization. For example, a JMenu or a JPopupMenu creates and returns a JMenuItem from an Action while a JToolBar creates and returns a JButton. The action is then paired with the newly created GUI component in two ways: the GUI component registers as a PropertyChangeListener for any property changes that might occur in the action object, while the action object registers as an ActionListener on the GUI component. Figure 3-1 shows the interactions between a menu item or toolbar and an Action.

Essentially, this means that if the menu item or button is selected by the user, the functionality inside the action is invoked. On the other hand, if the action is disabled, it sends a PropertyChangeEvent to both the menu item and the toolbar, causing them to disable and turn gray. Similarly, if the action's icon or name is changed, the menu and toolbar are automatically updated.

>i.e, changes in Action object properties cause update to GUI components and user actions in GUI components invoke Action object

3.1.2 The Action Interface
An action is defined by the interface it implements, in this case javax.swing.Action. Action extends the ActionListener interface from AWT; this forces concrete classes that implement Action to provide an actionPerformed( ) method. The programmer uses the actionPerformed( ) method to implement whatever behavior is desired. For example, if you are creating a Save action, you should put the code that saves the data inside of your actionPerformed( ) method.

When the action is added to an accepting container such as JMenu, JPopupMenu, or JToolBar, the container automatically registers the action as an ActionListener of the GUI component it creates. Consequently, if the GUI component is selected by the user, it simply invokes the actionPerformed( ) method of the action to do its job.

The Action interface defines five constants (shown in Table 3-2), which serve as keys for storing standardized Action properties. The method of storage varies from implementer to implementer, but a Hashtable is common. These properties store information such as the name of the action, its description, and a representative icon. Also, the Action interface defines a boolean property that indicates whether the action is enabled or disabled. Recall that the GUI component created for the action registers itself as a PropertyChangeListener. Hence, if any of these properties are modified, the GUI component is notified and can react accordingly.

Table 3-1. String-based key constants for the Action interface
Constant - Meaning

 Default setting

 Name of the action

 Short text description of what the action does

 Long text description of what the action does

 Represents a small icon; typically used in a toolbar Property
The Action interface defines the property shown in Table 3-2.

Table 3-2. Action property  Property
 enabled - boolean

The enabled property defines whether anyone can invoke the action. When this property changes, the action should fire a PropertyChangeEvent describing the change.

Note that the properties whose keys appear in Table 3-1 are not also shown here. These are really properties because changing one should fire a PropertyChangeEvent. However, because they do not use standard accessors, they do not fit the true JavaBeans property model, so we have omitted them from Table 3-2. Methods
public abstract Object getValue(String key)
public abstract void putValue(String key, Object value)
Store various keyed properties for the action. A string-based key is used to index the values. Several string constants representing the keys are shown in Table 3-1. When putValue( ) is called with any property, and the value passed in is different than what was there previously, the implementing object must fire a PropertyChangeEvent describing the change to all registered listeners.

public abstract void actionPerformed(ActionEvent e)
This method is required by the ActionListener interface (it does not actually exist in the Action interface). Any concrete class that implements the Action interface must provide an actionPerformed( ) method that performs whatever task the action is supposed to accomplish. Events
Objects implementing the Action interface must fire a PropertyChangeEvent when any keyed property is changed, or when the action is enabled or disabled. Containers that accept actions typically listen for these PropertyChangeEvent notifications so they can update their own properties or appearances.

public abstract void addPropertyChangeListener(PropertyChangeListener listener)
public abstract void removePropertyChangeListener(PropertyChangeListener listener)
Add or remove the specified PropertyChangeListener from the event listener list.

3.1.3 The AbstractAction Class
The AbstractAction class is an abstract implementation of the Action interface. AbstractAction provides the default functionality for almost all methods in the Action interface. You can extend this class to create your own specific actions. If you do so, the only method for which you must provide an implementation is the actionPerformed( ) method, which provides the functionality for the action. Here is a simple example:

class MyAction extends AbstractAction {
    public MyAction(String text, Icon icon) {
    public void actionPerformed(ActionEvent e) {
        System.out.println("Action [" + e.getActionCommand( ) + "]!");
Here, we simply print the action command sent with the ActionEvent. You can add more features based on the contents of the ActionEvent.

3.3.1 Headless Modes
One other variation on the graphics environment is "headless" operation. This mode of running without any monitor shows up quite often on back-end systems. Java servlets trying to use the AWT, 2D, and Swing classes to draw dynamic graphs for a web page are a classic example of applications that need a graphics environment on a machine that might not have any graphics displays. You can detect such a case with the GraphicsEnvironment.isHeadless( ) call.

If an environment is headless, there are certain calls that cannot be made. These calls tend to create onscreen components such as frames or dialogs—no good without a head—or otherwise attempt to interact with the (nonexistent) local user. Table 3-4 shows the documented Swing components that generate a HeadlessException when called. Since HeadlessException is an unchecked exception (i.e., a descendant of RuntimeException), it is not always documented in the Javadoc for a method or in its throws clause (in the source code). The best practice that has evolved for writing Javadoc for such exceptions requires that the Javadoc mention the exception (with an @throws entry), but that the throws clause in the actual method signature omit it. This leads to a visual indication that it is an unchecked exception. Not all code has adopted this best practice, of course.

Table 3-4. Swing components that throw HeadlessException  Component


 showDialog( ); setDragEnabled( ); createDialog( ); constructors


 createDialog( ); showDialog( ); showOpenDialog( ); showSaveDialog( ); setDragenabled( )


 setDragEnabled( )

 All show dialog methods; createDialog( ); getFrameForComponent( ); getWindowForComponent( ); getRootFrame( )

 setDragEnabled( )

 setDragEnabled( )


 getSharedOwnerFrame( )

3.4 Sending Change Events in Swing
Swing uses two different change event classes. The first is the standard java.beans.PropertyChangeEvent class. This class passes a reference to the object, sending the change notification as well as the property name, its old value, and its new value. The second, javax. swing.event.ChangeEvent, is a lighter version that passes only a reference to the sending object—in other words, the name of the property that changed, as well as the old and new values, are omitted.

 Since the ChangeEvent class is not part of the JavaBeans specifications, properties that use this event are not "bound" according to the JavaBeans standard. In order to prevent confusion, properties that use a ChangeEvent to notify listeners of property changes have not been marked as bound in our property tables.

Because the ChangeEvent includes only a reference to the event originator, which never changes, you can always define a single ChangeEvent and reuse it over and over when firing events from your component.

3.4.1 The ChangeEvent Class
The ChangeEvent is a stripped-down version of the java.beans.PropertyChangeEvent class. This class has no methods or properties, only a constructor. This simplicity makes it a popular class for developers wanting to fire off their own events. Recipients get a reference to the source of the event but then must query the source directly to find out what just happened. It's great for quick notifications or instances in which the state of the source component is so complex it's hard to predict which pieces of information the recipient will need, but it shouldn't be used simply to save the component author a little time at the expense of runtime inefficiency if the recipient always needs to look up information that could have been part of a PropertyChangeEvent. Constructor
public ChangeEvent(Object source)
The constructor for the ChangeEvent class. It takes only a single object, which represents the entity sending the event.

3.4.2 The ChangeListener Interface
Objects that intend to receive change events must implement the interface. They can then register to receive ChangeEvent objects from a publisher class. The ChangeListener interface consists of only one method. Method
public abstract void stateChanged(ChangeEvent e)
Implemented in a listener object to receive ChangeEvent notifications.

The ColorModel abstract class encapsulates the methods for translating a pixel value to color components (for example, red, green, and blue) and an alpha component. In order to render an image to the screen, a printer, or another image, pixel values must be converted to color and alpha components. As arguments to or return values from methods of this class, pixels are represented as 32-bit ints or as arrays of primitive types. The number, order, and interpretation of color components for a ColorModel is specified by its ColorSpace. A ColorModel used with pixel data that does not include alpha information treats all pixels as opaque, which is an alpha value of 1.0.
An Insets object is a representation of the borders of a container. It specifies the space that a container must leave at each of its edges. The space can be a border, a blank space, or a title.

3.5 The JComponent Class
JComponent is an abstract class that almost all Swing components extend; it provides much of the underlying functionality common throughout the Swing component library. Just as the java.awt.Component class serves as the guiding framework for most of the AWT components, the javax.swing.JComponent class serves an identical role for the Swing components. We should note that the JComponent class extends java.awt.Container (which in turn extends java.awt.Component), so it is accurate to say that Swing components carry with them a great deal of AWT functionality as well.

Because JComponent extends Container, many Swing components can serve as containers for other AWT and Swing components. These components may be added using the traditional add( ) method of Container. In addition, they can be positioned with any Java layout manager while inside the container. The terminology remains the same as well: components that are added to a container are said to be its children; the container is the parent of those components. Following the analogy, any component that is higher in the tree is said to be its ancestor , while any component that is lower is said to be its descendant.

Recall that Swing components are considered "lightweight." In other words, they do not rely on corresponding peer objects within the operating system to render themselves. As we mentioned in Chapter 1, lightweight components draw themselves using the standard features of the abstract Graphics object, which not only decreases the amount of memory each component uses but allows components to have transparent portions and take on nonrectangular shapes. And, of course, lightweight components are free of a dedicated L&F.

It's not out of the question to say that a potential benefit of using lightweight components is a decrease in testing time. This is because the functionality necessary to implement lightweight components in the Java virtual machine is significantly less than that of heavyweight components. Heavyweight components must be individually mapped to their own native peers. On the other hand, one needs to implement only a single lightweight peer on each operating system for all the Swing components to work correctly. Hence, there is a far greater chance that lightweight components will execute as expected on any operating system and not require rounds of testing for each platform.

 Because all Swing components extend Container, you should be careful that you don't add( ) to Swing components that aren't truly containers. The results range from amusing to destructive.

In JDK 1.2, JComponent reuses some of the functionality of the java.awt.Graphics2D class. This consists primarily of responsibilities for component painting and debugging.

3.5.1 Inherited Properties
Swing components carry with them several properties that can be accessed through JComponent but otherwise originate with AWT. Before we go any further, we should review those properties of java.awt.Container and java.awt.Component that can be used to configure all Swing components. This discussion is relatively brief; if you need a more thorough explanation of these AWT classes, see Java AWT Reference by John Zukowski (O'Reilly), which can be downloaded from this book's web site, Table 3-5 lists the properties that JComponent inherits from its AWT superclasses.

Table 3-5. Properties inherited from the AWT Component and Container classes  Property
 Data type
 Default value (if applicable)









 BorderLayout( )






Let's discuss these properties briefly. The background and foreground properties indicate which colors the component uses to paint itself. We should mention that with Swing the background property is disabled if the component is transparent (not opaque). The read-only colorModel property returns the current model used to translate colors to pixel values; generally, the user does not need to access this property. The font property lets you get or set the font used for displaying text in the component.

The indexed component property maintains a list of all the components inside the container. You can tell how many there are with the integer componentCount property. If you want to access all of them through a Component array, retrieve the components property. The insets property specifies the current insets of the container, while the layout property indicates which layout manager is managing the components of the container. Technically, this means that you can use any component as a container. Don't be misled; if a component doesn't seem like a reasonable container, it probably can't be used as one. (Don't, for example, try to add a JButton to a JScrollBar.) A number of components use these properties for internal, specialized layout managers and components.

The locale property specifies the internationalization locale for the application. The location property indicates the x,y coordinates of the component's upper-left corner in the container's coordinate space. If you want to see the location of the component's upper-left corner in screen coordinates, use the read-only locationOnScreen property.

The name property gives this component a string-based name that components can display if they choose. The parent property references the container that is acting as this component's parent, or null if there is none. The size property specifies the component's current height and width in pixels.

The showing property indicates whether the component is currently showing on the screen, while the visible property tells if the component is marked to be drawn on the screen. There's an odd, nonintuitive relationship between visible and showing. A component that is visible isn't necessarily showing. "Visible" means that a component is capable of being displayed; "showing" means that the component is actually displayed (though it may be obscured by something else). Most containers (JPanel, JFrame, etc.) are invisible by default; most other components (JButton, etc.) are visible by default. So if you add a JButton to an invisible JFrame, for example, the button is visible but not showing. It can be displayed but happens to be in a container that isn't currently displayed.

Finally, if the valid property is false, the component needs to be resized or moved by the component's layout manager. If it is true, the component is ready to be displayed.

>Container.invalidate() - mark as invalid(requiring component layout again)
>Container.validate() - layout the components properly
>JComponent.revalidate() = invalidate() + validate() --> it marks the root container in the component hierarchy as invalid by calling invalidate() and adds it to the list of components that must be validated; it the validation is later done in EDT thread after all currenty pending events are dispatched.

3.5.2 Common Methods
Here are some other frequently called methods for working with Swing components:

public Component add(Component comp)
public Component add(Component comp, int index)
public void add(Component comp, Object constraints)
public void add(Component comp, Object constraints, int index)
Add a component to the container, given the optional constraints and the current index.

public void remove(int index)
public void remove(Component comp)
public void removeAll( )
Remove the appropriate component from the container. The final method empties the entire container.

public void pack( )
This method of java.awt.Window resizes the window to encompass the preferred size of all the contained components, as placed by the current layout manager. It's a good idea to call pack( ) after you've added components to a top-level container with a layout manager, such as JFrame, JApplet, JDialog, and JWindow.

public void validate( )
public void invalidate( )
The invalidate( ) method is typically called on a Container to indicate that its children need to be laid out, or on a Component to indicate that it needs to be re-rendered. This method is often called automatically. However, certain changes to a Component (such as changing the size of a button by changing its label or font) do not cause it to be invalidated. In such cases, invalidate( ) must be called on the Component to mark it as invalid, and validate( ) must be called on its Container. The validate( ) method is typically called to validate, lay out, and repaint a Container. Calling this method is especially important when you add or remove Components in a Container that is already displayed.

Swing improves the validate( )/invalidate( ) situation a bit by calling invalidate( ) in response to many property changes, saving you from having to make the call. Unfortunately, there are still situations (such as changing a JButton's font) that do not trigger an automatic invalidate( ) call, so you'll still have to explicitly call invalidate( ) in these cases.

The key things to take away from these methods are:

You may need to call invalidate( ) if you make changes to the appearance of a displayed component.

You must call validate( ) on Containers that have been invalidated (typically by the addition or invalidation of a child).

As a result of deprecation and the movement toward JavaBeans accessors, AWT has some methods with multiple names. For example, show( ) and setVisible(true) are essentially the same. It is always better to use the JavaBeans-style name—setVisible( ) in this case—when working with Swing; the newer name is less confusing for people familiar with the JavaBeans conventions.

3.5.4 UI Delegates and UIClassIDs
As we mentioned in Chapter 1, all Swing components use a modified MVC architecture. Each Swing component is responsible for maintaining two unique objects: a model and a UI delegate. The object representing the model handles the state information specific to the component while the UI delegate determines how the component paints itself based on the model's state information.

Note that there is no property for a model in JComponent. You typically access the model property at the level of a JComponent subclass. This is because each Swing component defines its own data model, which is unique from that of all other components. The UI delegate property, on the other hand, can be handled at the JComponent level because the methods for rendering lightweight components are always the same. These methods (e.g., installUI( ), uninstallUI( ), setUI( ), paint( )) can be traced back to the abstract class javax.swing.plaf.ComponentUI, which serves as the superclass for all UI delegates.

JComponent contains a reference to the current UI delegate for the object. JComponent allows a subclass to alter the component's UI delegate with the protected setUI( ) method; this method effectively resets the L&F of the component. The UI therefore acts like a write-only property, but we hesitate to call it a property because its mutator isn't public. Invoking setUI( ) by itself, however, does not change the display. A call to updateUI( ) is also required, which forces the component to redraw itself. If you are looking to change the entire L&F of the application, it is better to change it universally with the setLookAndFeel( ) method of UIManager than to change it one component at a time. See Chapter 2 for a simple example of how to work with various L&Fs.

Each Swing component maintains a read-only string constant, UIClassID, that identifies the type of UI delegate that it uses. Most Swing components override the accessor getUIClassID( ) and return a string constant, typically the letters "UI" appended to the name of the component (without the "J"). This string is then used by Swing's UI manager to match the component with a UI delegate for the current L&F. For example, a JButton object has a UIClassID string of ButtonUI. If the current L&F is Metal, the UIManager can figure out that the MetalButtonUI is the correct UI-delegate class to use

>UIDelegate does the paint()
>RepaintManager does the repaint()
>JComponent is responsible for paiting the component, its border and its children in that order(thru UIDelegate of course)

Components drawn last are always on top; hence, child components always paint over their parents. JComponent contains three protected methods that it uses to complete this functionality:

protected void paintComponent(Graphics g)

protected void paintBorder(Graphics g)

protected void paintChildren(Graphics g)

>similar to above methods, print methods were introduced but they internally call the above methods only. This is to allow users to add any special treatments while printing the components

printComponent(Graphics g) { paintComponent(g);}
printBorder(Graphics g) { paintBorder(g);}
printChildren(Graphics g) { paintChildren(g);}

>transparent component's background is ignored

>JComponent can optimize its repainting time if none of its children overlap; this is because the repaint manager does not have to compute the hidden and visible areas for each child component before rendering them. Some containers, such as JSplitPane, are designed so that overlap between child components is impossible, so this optimization works nicely. Other containers, such as JLayeredPane, have support for child components that can overlap. JComponent contains a property that Swing frequently calls upon to see if it can optimize component drawing: optimizedDrawingEnabled. In JComponent, this property is set to true by default. If overlap occurs in a subclass of JComponent, the subclass should override the isOptimizedDrawingEnabled( ) accessor and return false. This prevents the repaint manager from using the optimized drawing process when rendering the container's children.

JComponent contains a boolean read-only property (paintingTile) that indicates whether the component is currently in the process of painting a tile , which is a child component that does not overlap any other children. The isPaintingTile( ) method returns true until all tiles have been painted.

>The validateRoot property is false by default. If it is set to true, it designates this component as the root component in a validation tree. Recall that each time a component in a container is invalidated, its container is invalidated as well, along with all of its children. This causes an invalidation to move all the way up the component hierarchy, stopping only when it reaches a component for which isValidateRoot( ) returns true. Currently, the only components that set this property to true are JRootPane (which is used by all the Swing top-level components), JScrollPane, and JTextField.

>The visibleRect property is a Rectangle that indicates the intersection of the component's visible rectangles with the visible rectangles of all of its ancestors. Why the intersection? Remember that you can have a contained object that is clipped by its parent. For example, you can move an internal frame so that a portion of it falls outside the parent window's clipping region. Therefore, the visible portion (the portion that is actually drawn to the screen) consists only of the intersection of the parent's visible portion and the child's visible portion. You typically do not need to access this property.

>The topLevelAncestor property contains a reference to the top-level window that contains this component, usually a JWindow or JApplet.

>location[x,y] - position of the upper left corner of the component relative to the parents coordinate space
 x - horizontal distance(of upper left corner of the child) from parent's upper left corner
 y - vertical downwards distance(of upper left corner of the child) from parent's upper left corner
 size = width and height of the child from point(x,y)
 bounds = Rectangle(x,y,width,height)

>If a Rectangle is supplied, the getBounds( ) method alters each of the fields in the passed-in Rectangle to reflect the component's current size and position, returning a copy of it. If the reference passed in is a null, the method instantiates a new Rectangle object, sets its values, and returns it. You can use the former approach to reduce the number of garbage rectangles created and discarded over multiple calls to getBounds( ), which increases the efficiency of your application.

>The setBounds( ) method alters the component's size and position. This method also takes a Rectangle object. If the new settings are different from the previous settings, the component is moved, typically resized, and invalidated. If the component has a parent, it is invalidated as well. Be warned that various layout managers may override any changes you attempt to make to the bounds property. Invalidating a component with a call to setBounds( ) may force the layout manager to recompute and reset the bounds of the component in relation to the other components, resolving it to the same size as before.

>You can still use the setSize( ) and setLocation( ) methods of java.awt.Component if you prefer to code with those as well. Again, note that when altering the size of the component, the layout manager may override the new value and reset it to its previous value, thus ignoring your new size values.

The three well-known AWT sizing properties, minimumSize, preferredSize, and maximumSize, are accessible through JComponent. minimumSize indicates the smallest size for the component when it is in a container. preferredSize contains the size at which the container's layout manager should strive to draw the component. maximumSize indicates the largest size the component should be when displayed in a container. If none of these properties are set by the user, they are always calculated by the component's UI delegate or directly by the layout manager of the container, in that order. The methods setMinimumSize( ), setPreferredSize, and setMaximumSize( ) allow you to change these properties without subclassing.

>Finally, JComponent contains two read/write properties that help interested layout managers align the component in a container: alignmentX and alignmentY. Both of these properties contain floating-point values between 0.0 and 1.0; the numbers determine the position of the component relative to any siblings. A number closer to 0 indicates that the component should be positioned closer to the left or top side, respectively. A perfect 0.5 indicates that the component should be placed at the center, while a number nearing 1 indicates that the component should be positioned closer to the right or bottom. Currently, the only layout managers that use these properties are the BoxLayout and OverlayLayout managers; all AWT 1.1 layout managers ignore these properties and position their children by other means.

>It's easy to add borders to Swing components, a feature AWT lacks.
>One important characteristic of Swing is that if a border property is set on a component, the border overrides the component's insets property. Swing allows the programmer to specify an empty border, so you can still pad the component with extra space as well as provide a border if you use a CompoundBorder. If the border property is null, the default insets are used for the component instead.
>CompoundBorder - stacking multiple borders on top of each other

3.5.8 Working with Tooltips
JComponent also provides Swing components with support for tooltips. Tooltips are small windows of text that pop up when the user rests the mouse over the target component. They typically supplement the meaning of an icon or button, but they can also provide the user with instructions or important information about the underlying component. The tooltip usually disappears after a designated amount of time (four seconds by default) or if the mouse is moved outside of the component's bounds.

JComponent does not manage tooltips by itself; it gets help from the ToolTipManager class. The ToolTipManager continually scans for mouse events on components that have tooltips. When the mouse passes into a component with a tooltip set, the ToolTipManager begins a timer. If the mouse has not left the component's region in 0.75 seconds, a tooltip is drawn at a preset location near the component. If the mouse has moved out of a region for longer than 0.5 seconds, the tooltip is removed from the screen.

With the default setToolTipText( ) and getToolTipText( ) methods, JComponent handles the creation of an appropriate tooltip. If you want to get more creative, however, Swing provides a separate object for tooltips: JToolTip. With it, you can completely redefine the characteristics of a tooltip by declaring your own JToolTip object and overriding the createToolTip( ) method of JComponent to return it to the ToolTipManager on demand.

3.5.9 Client Properties
Swing components can maintain a special table of properties called "client properties." This provides specialized properties that can be meaningful in components only in certain instances. For example, let's assume that a specific L&F uses a client property to store information about how a component should display itself when that L&F is activated. As you might guess, this client property would be meaningless when another L&F is activated. Using the client properties approach allows various L&Fs to expand their component properties without deluging the Swing source base with L&F-specific data.

The name "client properties" is somewhat confusing because client properties are distinct from JavaBeans-style properties. Obviously, there's a big difference: unlike JavaBeans properties, you can create new client properties without subclassing; you can even create new client properties at runtime. These two methods in JComponent store and retrieve client properties:

myComponent.putClientProperty("aClientProperty", Boolean.TRUE);
Boolean result = (Boolean)getClientProperty("aClientProperty");
Because we are using a hashtable, the properties must be objects and not primitive data types; we must use the Boolean object instead of simply setting true or false.

3.5.10 Double Buffering
The JComponent class allows all Swing components to take advantage of double buffering. The idea behind double buffering is that it takes longer for a component to render its individual parts on screen than it does for a rectangular-area copy to take place. If the former occurs over multiple screen refreshes, the human eye is likely to catch the component in the process of being drawn, and it may appear to flicker. With the latter, the screen is usually updated as fast as the monitor can refresh itself.[2]

[2] Area copies are always faster because they are performed by the operating system or even the graphics card of the computer. At this level, they are commonly referred to as "bit-block transfers," or BitBLTs.

When double buffering is activated in Swing, all component rendering performed by the repaint manager is done in an offscreen buffer. Upon completion, the contents of the offscreen buffer are quickly copied (not redrawn) on the screen at the component's position. You can request double buffering for a particular component by accessing the boolean doubleBuffered property of JComponent. Passing in true to the setDoubleBuffered( ) method enables double buffering; false shuts it off:

JButton button = new JButton("Test Button");
button.setDoubleBuffered(true);    // Turns on double buffering
You can use the isDoubleBuffered( ) method to check if double buffering is currently enabled on a Swing component. The component level setting is only a request, and Swing double buffering may be completely disabled at the level of the repaint manager (for example, when running under an operating system like Mac OS X, double buffering is always performed by the window manager, so doing it again in Swing would simply throw away processor cycles for no benefit). See Section 28.4.2 for more details and for information about how you can use graphics-accelerated "volatile images" in SDK 1.4 to further speed up Swing double buffering.

With double buffering, transparency is maintained in nonopaque components because the graphics underneath the component are copied into the buffer before any offscreen rendering takes place. However, there is a slight penalty for double buffering nonopaque components because Swing performs two area copies instead of one: one to copy the context in which the component is drawn to the offscreen buffer before drawing, and one to copy this context plus the rendered component back to the screen.

Buffers also chew up a great deal of memory, so the repaint manager tries to avoid using more than one offscreen buffer at a time. For example, if an offscreen buffer has been set for both a container and one of its children, the buffer for the parent container is used for both components.

3.5.12 The DebugGraphics Class
Lightweight components are rendered entirely in Java, as opposed to offloading their work to a native heavyweight peer. The abstract Graphics class outlines platform-independent implementations for line-drawing, image-painting, and area-copying and filling that a lightweight peer can call upon to draw itself. If you create your own component, or extend an existing one, a Graphics object is often passed to the UI delegate's paint( ) method to help with the drawing.

Sometimes the way you intend a component to be painted, however, isn't how it appears on the screen. Debugging painting problems can prove to be troublesome, especially when dealing with transparency, opaqueness, and double buffering. JComponent, however, can generate a special version of the Graphics object, called DebugGraphics, which it can pass to a UI delegate's paint( ) method. This object can take a set of user-configurable debugging options that modify how a component is drawn to the screen.

If you wish to activate debugging for the component's graphics, you can pass one or more debugging flags (see Table 3-7) into JComponent's setDebugGraphicsOptions( ) method.

Table 3-7. Constants for DebugGraphics options  DebugGraphics constant

 Causes each graphics primitive to flash a configurable number of times as it is being rendered.

 Prints a text message to the screen as each graphics primitive is drawn.

 Raises a window that shows the drawing that is taking place in the offscreen buffer. This is useful in the event that the double-buffered feature has been activated.

 Disables all debug graphics options.

The debug options outlined in Table 3-7 are bits in a binary mask; you can set more than one at the same time by using the bitwise OR ( | ) operator, as shown here:

JButton myButton = new JButton("Hello");  // JButton extends JComponent.
                                       | DebugGraphics.LOG_OPTION);
When any of the debug graphics options are set, the getComponentGraphics( ) method of JComponent returns a DebugGraphics object instead of a normal Graphics object. As we mentioned earlier, the same type of object is passed to the UI delegate of the component. When a component draws itself, it calls upon the functionality of the DebugGraphics object to perform the task, just as it would with a typical Graphics object. The drawing primitives are then slowed or logged so that the user can help identify any problems.

Focus Cycle
Focus - component having focus is responsible for consuming keyboard and mouse events
Focus Cycle - set of components that can be traversed using Tab key in a cyclic manner

>A group of components within a single container can define a focus cycle of its own. If the container has its own focus cycle, the focus repeatedly traverses through all of its children that accept the focus. The focus cycle is typically determined by the location of components in the container, although you can create your own focus traversal policy if you require different behavior. With the default focus policy, the component closest to the top-left corner of the container always receives focus first. The focus then moves from left to right across the components, and from top to bottom. Figure 3-9 shows how the default focus cycle shifts focus between components in a container.

>If a container has a focus cycle of its own, it should override the Container method isFocusCycleRoot( ) and return true. If the method returns true, then the container is known as the root container of the focus cycle.

With SDK 1.2 or 1.3, you can explicitly name the component that should receive the focus after a given JComponent by setting its nextFocusableComponent property. In addition, focus can be programmatically requested through the JComponent method requestFocus( ), which the focus manager can call to shift the focus to this component. This is often done when the user selects the object (i.e., presses a JButton). If you don't want your component to be able to respond to requestFocus( ) calls, you can set the requestFocusEnabled property of JComponent to false.

With SDK 1.4, this method of managing focus was replaced by the more flexible FocusTraversalPolicy class as part of a major overhaul of the whole focus system. This class allows you to define a focus policy to manage a container. (In this case, "focus policy" simply means an algorithm to figure out which component follows, and which one precedes, the current component in the focus cycle.) One advantage of moving to policy-based management is that generic policies can be developed for containers—no more need to hook up individual components.

There is an important distinction here: setting the requestFocusEnabled property to false does not mean that the focus cannot be traversed onto your component; it simply means that it cannot be programmatically requested. JComponent provides a similar property, focusable,[4] that you can enable or disable to specify whether a component ever receives focus at all.

>3.5.14 Keyboard Events
Swing components can be programmed to trigger various actions when certain keystrokes occur. For example, components automatically handle focus-related keyboard events. The default focus mechanism watches for Tab and Shift-Tab keystrokes, adjusting the focus and consuming the keystrokes. If the focus mechanism does not know how to handle a keystroke, and no registered low-level KeyListeners have consumed it, JComponent checks to see whether the processComponentKeyEvent( ) method consumes it. The default implementation does nothing, the idea being that you can override it in a subclass if you want to react to a keystroke in your own way. You're not likely to want to use that approach, though, because it's much less flexible than what happens next: if nothing has consumed the key event, JComponent checks to see if a keyboard action has been registered for that keystroke. A set of maps provide a convenient way to translate key events to appropriate component-related actions.

Translation to an action starts by converting the key event to the KeyStroke that represents it. This is used as a key to check the component's InputMap for a corresponding action name (the InputMap could return any kind of object, but convention dictates that it be a String corresponding to a logical action name). The result of this lookup, if not null, is used in turn as a key to look in the component's ActionMap for an Action to perform. Assuming that a non-null Action was found, its actionPerformed method is invoked (as described in Section 3.1.2 earlier in this chapter).

It might seem like overkill to use a two-map lookup like this. Wouldn't it be simpler to just put the Actions directly in the InputMap? It turns out there are a couple of good reasons for the second layer. Although a given type of component generally supports a well-defined set of logical operations, the specific Action classes that implement them often vary depending on the L&F in use. Similarly, the keys that are used to invoke the actions vary between L&Fs, which leads to a complex coupling between the component and the L&F-specific UI delegate. Separating the two concepts into two maps provides an easy-to-understand translation between KeyStrokes and logical event names, and from event names to specific Action implementations. It also means that InputMaps are nicely self-documenting; it's easy to turn them into a human-readable table that shows the functions assigned to various keys.[5]

[5] For more details about the design goals of this key-binding mechanism, which was introduced in SDK 1.3, see, which also describes the limitations of the previous mechanism. If you are still working with a pre-1.3 version of Swing, you can find the first edition's version of this section, which discusses how to use the old key-binding mechanism, on this book's web site,

InputMaps and ActionMaps are also designed to be easy to share between components (or even similar component types). They have a parent property that is checked if a binding isn't found, so common functionality can be placed in a shared parent map, and component-specific definitions added to a local map on an as-needed basis; the text components make extensive use of this capability. JComponent makes this easy by providing newly initialized components with empty InputMaps and ActionMaps whose parents are the (likely shared) map provided by the UI. So, as a developer, you never need to worry about the possible existence of shared maps; you can just start adding your custom mappings and rely on Swing to provide the rest.

Before showing you the details of how to register keyboard actions, there is one more complication to clarify. The process outlined here described a single InputMap used to translate keystrokes to action names. In fact, components have three separate InputMaps to address the fact that there are different situations under which a component might be asked to respond to a keyboard event. The most obvious case, which probably sprang to mind, is when the component itself is the owner of the keyboard focus. Components can also have a chance to respond to key events if they don't have focus in two other cases. First, a component may respond if it is an ancestor of (contains) the focused component. Think of a ScrollPane, in which the Page Up and Page Down keys remain functional even though you're working with the contents of the pane rather than the pane itself. Second, a component may respond if it is simply inside a window that is focused (this is how button mnemonics work). In order to create the proper InputMap, the methods to manipulate them offer a condition parameter whose legal values are shown in Table 3-8.

Table 3-8. Constants for InputMap selection  Constant

 The InputMap used when the component has the focus

 The InputMap used when the component resides in a container that has the focus

 The InputMap used when the component is the ancestor of (contains) the component that currently has the focus

You obtain a component's input map through one of the following two methods (these were mentioned in Table 3-6, but bear repeating in this context):

public InputMap getInputMap(int condition)
Return the input map to be used under the specified condition.

public InputMap getInputMap( )
A convenience method that calls getInputMap(WHEN_FOCUSED), which is the most commonly used condition.

Looking up the action map is simpler since there's only one method:

public ActionMap getActionMap( )
Return the action map associated with the component.

A brief example illustrates how to perform the common task of assigning an event to a component using this binding mechanism. Suppose we wanted to extend the example program in Section to perform a download whenever the F8 key is pressed. One way we could do this is by adding the following lines to the end of the ActionExample constructor:

exampleButon.getActionMap( ).put("download", exampleAction);
  KeyStroke.getKeyStroke("F8"), "download");
The first line binds the logical action name download to our sample download action within the button's action map. The second line causes the F8 key to trigger this logical action whenever the button's window has the focus, even if the button itself does not. This two-step registration process in which both an InputMap and the ActionMap are retrieved and modified is very common when working with custom actions because of the two-stage, key-mapping process. If you're simply changing or adding bindings for a standard keystroke or action, you need to work with only one of the maps.

To remove a binding you've set, both types of maps provide a remove method that takes a KeyStroke object that will be removed from the mapping. The clear method removes all mappings. Neither of these methods affect inherited mappings. In fact, if you added a keystroke that overrode an inherited mapping, removing that keystroke restores the inherited mapping. If you actually want to block an inherited mapping without providing a new action, register a mapping to the action "none", which convention mandates never has an Action bound to it.

There are corresponding methods for setting the map properties themselves, of course. These are used far less commonly, but do provide a way to eliminate the inherited parent maps provided by the L&F's UI delegate:

public void setInputMap(int condition)
public void setActionMap(ActionMap actionMap)
Replace the corresponding map completely, eliminating any inherited mappings. Passing a null argument causes the component to have no bindings at all.

Note that if you replace the mappings this way, there's no way to get back the previously inherited mappings unless you keep a reference to the original maps yourself.


>Swing is part of the Java Foundation Classes (JFC). The JFC also include other features important to a GUI program, such as the ability to add rich graphics functionality and the ability to create a program that can work in different languages and by users with different input devices.

>Pluggable Look-and-Feel Support
Any program that uses Swing components has a choice of look and feel. The JFC classes shipped by Sun and Apple provide a look and feel that matches that of the platform. The Synth package allows you to create your own look and feel. The GTK+ look and feel makes hundreds of existing look and feels available to Swing programs.

A program can specify the look and feel of the platform it is running on, or it can specify to always use the Java look and feel, and without recompiling, it will just work. Or, you can ignore the issue and let the UI manager sort it out.

>Accessibility API
People with disabilities use special software — assistive technologies — that mediates the user experience for them. Such software needs to obtain a wealth of information about the running application in order to represent it in alternate media: for a screen reader to read the screen with synthetic speech or render it via a Braille display, for a screen magnifier to track the caret and keyboard focus, for on-screen keyboards to present dynamic keyboards of the menu choices and toolbar items and dialog controls, and for voice control systems to know what the user can control with his or her voice. The accessibility API enables these assistive technologies to get the information they need, and to programmatically manipulate the elements that make up the graphical user interface.

>JFC = Swing + Pluggable LAF + Accessibility API + 2D API + Internationalization (AWT not part of JFC?)

>Swing provides three general top level containers: JFrame, JDialog and JApplet

>Each GUI component can be contained only once. If a component is already in a container and you try to add it to another container, the component will be removed from the first container and then added to the second.

>Each top-level container has a content pane that, generally speaking, contains (directly or indirectly) the visible components in that top-level container's GUI.

>You can optionally add a menu bar to a top-level container. The menu bar is by convention positioned within the top-level container, but outside the content pane. Some look and feels, such as the Mac OS look and feel, give you the option of placing the menu bar in another place more appropriate for the look and feel, such as at the top of the screen.

>Note:  Although JInternalFrame mimics JFrame, internal frames aren't actually top-level containers.

>Content Pane and Menu Bar are parallel(peers) to each other

Containment Hierarchy
>Top level container is the root of the containment hierarchy
>Every top level container has its own containment hierarchy

>JFrame.getContentPane() returns javax.swing.JPanel
>But the return type of getContentPane() method is 'Container'
>the default content pane uses BorderLayout as its layout manager
>the default layout for JPanel is FlowLayout
>you can set your own content pane using setContentPane() in the top level container

>Note: As a convenience, the add method and its variants, remove and setLayout have been overridden to forward to the contentPane as necessary. This means you can write
and the child will be added to the contentPane.

Note that only these three methods do this. This means that getLayout() will not return the layout set with setLayout().

>Adding menu bar: JFrame.setJMenuBar()

>a reclusive pane used by top-level containers
>RootPane manages content pane, menu bar and couple of other containers(LayeredPane and GlassPane)
>you need to know RootPane to intercept mouse clicks or to paint over multiple components

Panes from Bottom to Top

Frame -> RootPane -> LayeredPane -> ContentPane + MenuBar -> GlassPane

>LayeredPane contains ContentPane and MenuBar
>LayeredPane enables z-ordering of other components
>GlassPane is used to intercept input events occuring over top-level containers
>GlassPane is also used to paint over multiple components

>Except for top-level containers all other components whose name start with J are descendants of JComponent
>JFrame, JDialog and JApplet derive from AWT containers not from JComponent
>JPanel, JScrollPane, JButton, JTable, etc derive from JComponent
>AWT component hierarchy from parent to child

 java.lang.Object <- java.awt.Component <- java.awt.Container <- java.awt.Window <- java.awt.Frame/java.awt.Dialog

  java.awt.Container <- java.awt.Panel <- java.applet.Applet

>JFrame, JDialog and JApplet derive from their equivalent awt components (Frame, Dialog and Applet respectively)
>JComponent extends java.awt.Container
>java.awt.Component is the root of all UI related components
>java.awt.Component includes everything from providing layout hints to supporting painting *and* events
>java.awt.Container has support for adding components and laying out them
>JComponent Features:
2.Painting and borders
3.Application-wide pluggable look and feel
4.Custom properties
5.Support for layout
6.Support for accessibility
7.Support for drag and drop
8.Double buffering
9.Key bindings

setToolTipText() - set tool tip
setBorder() - sets the border outside
paintComponent() - painting insides of the component

Application-wide pluggable look and feel -
Behind the scenes, each JComponent object has a corresponding ComponentUI object that performs all the drawing, event handling, size determination, and so on for that JComponent. Exactly which ComponentUI object is used depends on the current look and feel, which you can set using the UIManager.setLookAndFeel method.

putClientProperty()/getClientProperty() - set custom properties to component as name/object pairs(e.g. constraints objects)
getPreferredSize()/getAlignmentX()/setMinimumSize()/setMaximumSize()/setAlignmentX()/setAlignmentY() - layout support methods
double buffering - smooths on screen painting


>Get the preferred, maximum, or minimum size of the component, measured in pixels. Many JComponent classes have setter and getter methods. For those non-JComponent subclasses, which do not have the corresponding setter methods, you can set a component's preferred, maximum, or minimum size by creating a subclass and overriding these methods.

>Insets getInsets() Get the size of the component's border.

>void setBounds(int, int, int, int)
void setBounds(Rectangle) Set the size and location relative to the parent's upper left corner, in pixels, of the component. The four int arguments specify x, y, width, and height, in that order. Use these methods to position and size a component when you are not using a layout manager.

Text Components
>Swing provides six text components, along with supporting classes and interfaces that meet even the most complex text requirements. In spite of their different uses and capabilities, all Swing text components inherit from the same superclass, JTextComponent, which provides a highly-configurable and powerful foundation for text manipulation.

>JTextField - one line unstyled text
JFormattedTextField - preformatted(e.g. date format) one line plain text
JPasswordField - password masking
JTextArea - multiline plain text; any font can be used; but all texts will be in a single font style only at a time
JEditorPane - styled multi line multi font, html markup supported pane; can include icons
JTextPane - styled text pane same as JEditorPane but also includes embedded components like Button

>Each editing command is represented and implemented by an Action object. Actions allow you to associate a command with a GUI component, such as a menu item or button, and therefore build a GUI around a text component.

>Note: By default, each undoable edit undoes a single character entry. It is possible with some effort to group edits so that a series of key strokes is combined into one undoable edit. Grouping edits in this manner would require you to define a class that intercepts undoable edit events from the document, combining them if appropriate and forwarding the results to your undoable edit listener.

>A text component's model is known as a document and is an instance of a class that implements the Document interface. A document provides the following services for a text component:

Contains the text. A document stores the textual content in Element objects, which can represent any logical text structure, such as paragraphs, or text runs that share styles. We do not describe Element objects here. However, The Swing Connection has at least one article on the subject.
Provides support for editing the text through the remove and insertString methods.
Notifies document listeners and undoable edit listeners of changes to the text.
Manages Position objects, which track a particular location within the text even as the text is modified.
Allows you to obtain information about the text, such as its length, and segments of the text as a string.

>AbstractDocument implements Document
 PlainDocument extends AbstractDocument
 DefaultStyledDocument extends AbstractDocument implements StyledDocument
 HTMLDocument extends DefaultStyledDocument

>TextFields, PasswordFields and TextAreas use PlainDocument as a default document
>Oddly EditorPane(styled component) also uses PlainDocument by default
>TextPane uses DefaultStyledDocument by default
>To customize documents used by text components, use custom document or DocumentFilter

Document Filter
>filters are used to police the modifications to the document
>filters are called before the modification is committed to the documents
>document listeners are called after the modifications are committed to the documents
>You may want to change the document's text within a document listener. However, you should never modify the contents of a text component from within a document listener. If you do, the program will likely deadlock. Instead, you can use a formatted text field or provide a document filter.
>use caret listener to get updated about caret position and text selection
>use navigation filter to customize caret appearance and text selection
>use DefaultEditorKit to perform editing actions/caret movement actions within text document
>use StyledEditorKit to perform markup/html related editing actions on texts

Editor Kits
>Text components use an EditorKit to tie the various pieces of the text component together. The editor kit provides the view factory, document, caret, and actions. An editor kit also reads and writes documents of a particular format. Although all text components use editor kits, some components hide theirs. You cannot set or get the editor kit used by a text field or text area. Editor panes and text panes provide the getEditorKit method to get the current editor kit and the setEditorKit method to change it.


>Insets - specifies the size of the border

>At most one button in a top-level container can be the default button. The default button typically has a highlighted appearance and acts clicked whenever the top-level container has the keyboard focus and the user presses the Return or Enter key.

>if an applet uses Swing components it has to inherit from JApplet
>the only heavy weight swing containers: JFrame, JDialog, JWindow and JApplet
>light weight swing container: JInternalFrame
>interface RootPaneContainer is to mark the container as a user of single RootPane. all swing top-level containers implement RootPaneContainer interface; provides methods to get/set GlassPane, ContentPane and LayeredPane; and to get RootPane
>The diagram at right shows the structure of a JRootPane. A JRootpane is made up of a glassPane, an optional menuBar, and a contentPane. (The JLayeredPane manages the menuBar and the contentPane.) The glassPane sits over the top of everything, where it is in a position to intercept mouse movements. Since the glassPane (like the contentPane) can be an arbitrary component, it is also possible to set up the glassPane for drawing. Lines and images on the glassPane can then range over the frames underneath without being limited by their boundaries.
>Although the menuBar component is optional, the layeredPane, contentPane, and glassPane always exist. Attempting to set them to null generates an exception.
>To add components to the JRootPane (other than the optional menu bar), you add the object to the contentPane of the JRootPane, like this:


The same principle holds true for setting layout managers, removing components, listing children, etc. All these methods are invoked on the contentPane instead of on the JRootPane.

>Note: The default layout manager for the contentPane is a BorderLayout manager. However, the JRootPane uses a custom LayoutManager. So, when you want to change the layout manager for the components you added to a JRootPane, be sure to use code like this:
    rootPane.getContentPane().setLayout(new BoxLayout());

>If a JMenuBar component is set on the JRootPane, it is positioned along the upper edge of the frame. The contentPane is adjusted in location and size to fill the remaining area. (The JMenuBar and the contentPane are added to the layeredPane component at the JLayeredPane.FRAME_CONTENT_LAYER layer.)

>The layeredPane is the parent of all children in the JRootPane -- both as the direct parent of the menu and the grandparent of all components added to the contentPane. It is an instance of JLayeredPane, which provides the ability to add components at several layers. This capability is very useful when working with menu popups, dialog boxes, and dragging -- situations in which you need to place a component on top of all other components in the pane.

>The glassPane sits on top of all other components in the JRootPane. That provides a convenient place to draw above all other components, and makes it possible to intercept mouse events, which is useful both for dragging and for drawing. Developers can use setVisible on the glassPane to control when the glassPane displays over the other children. By default the glassPane is not visible.

>The custom LayoutManager used by JRootPane ensures that:

The glassPane fills the entire viewable area of the JRootPane (bounds - insets).
The layeredPane fills the entire viewable area of the JRootPane. (bounds - insets)
The menuBar is positioned at the upper edge of the layeredPane.
The contentPane fills the entire viewable area, minus the menuBar, if present.
Any other views in the JRootPane view hierarchy are ignored.

>If you replace the LayoutManager of the JRootPane, you are responsible for managing all of these views. So ordinarily you will want to be sure that you change the layout manager for the contentPane rather than for the JRootPane itself!

>A check box generates one item event and one action event per click. Usually, you listen only for item events, since they let you determine whether the click selected or deselected the check box.

>You can use ButtonGroup with any set of objects that inherit from AbstractButton. Typically a button group contains instances of JRadioButton, JRadioButtonMenuItem, or JToggleButton. It would not make sense to put an instance of JButton or JMenuItem in a button group because JButton and JMenuItem do not implement the select/deselect button state.

Removing or Replacing the Preview Panel

By default, the color chooser displays a preview panel. ColorChooserDemo2 removes the text color chooser's preview panel with this line of code:
tcc.setPreviewPanel(new JPanel());
This effectively removes the preview panel because a plain JPanel has no size and no default view. To set the preview panel back to the default, use null as the argument to setPreviewPanel.

Creating a Custom Chooser Panel
The default color chooser provides five chooser panels:
Swatches — for choosing a color from a collection of swatches.
HSV — for choosing a color using the Hue-Saturation-Value color representation. Prior to JDK 7, this was called HSB, for Hue-Saturation-Brightness.
HSL — for choosing a color using the Hue-Saturation-Lightness color representation. This is new in JDK 7.
RGB — for choosing a color using the Red-Green-Blue color model.
CMYK — for choosing a color using the process color or four color model. This is new in JDK 7.
You can extend the default color chooser by adding chooser panels of your own design with addChooserPanel, or you can limit it by removing chooser panels with removeChooserPanel.
If you want to remove all of the default chooser panels and add one or more of your own, you can do this with a single call to setChooserPanels. ColorChooserDemo2 uses this method to replace the default chooser panels with an instance of CrayonPanel, a custom chooser panel. Here is the call to setChooserPanels from that example:

//Override the chooser panels with our own.
AbstractColorChooserPanel panels[] = { new CrayonPanel() };
The code is straighforward: it creates an array containing the CrayonPanel. Next the code calls setChooserPanels to set the contents of the array as the color chooser's chooser panels.
CrayonPanel is a subclass of AbstractColorChooserPanel and overrides the five abstract methods defined in its superclass:

void buildChooser()
Creates the GUI that comprises the chooser panel. The example creates four toggle buttons — one for each crayon — and adds them to the chooser panel.
void updateChooser()
This method is called whenever the chooser panel is displayed. The implementation of this method selects the toggle button that represents the currently selected color.
public void updateChooser() {
    Color color = getColorFromModel();
    if ( {
    } else if (Color.yellow.equals(color)) {
    } else if ( {
    } else if ( {
String getDisplayName()
Returns the display name of the chooser panel. The name is used on the tab for the chooser panel. Here is the example getDisplayName method:
public String getDisplayName() {
    return "Crayons";
Icon getSmallDisplayIcon()
Returns a small icon to represent this chooser panel. This is currently unused. Future versions of the color chooser might use this icon or the large one to represent this chooser panel in the display. The example implementation of this method returns null.
Icon getLargeDisplayIcon()
Returns a large icon to represent this chooser panel. This is currently unused. Future versions of the color chooser might use this icon or the small one to represent this chooser panel in the display. The example implementation of this method returns null.

Combo boxes require little screen space, and their editable (text field) form is useful for letting the user quickly choose a value without limiting the user to the displayed values. Other components that can display one-of-many choices are groups of radio buttons and lists. Groups of radio buttons are generally the easiest for users to understand, but combo boxes can be more appropriate when space is limited or more than a few choices are available. Lists are not terribly attractive, but they're more appropriate than combo boxes when the number of items is large (say, over 20) or when selecting multiple items might be valid.

Note:  Be careful when implementing a custom model for a combo box. The JComboBox methods that change the items in the combo box's menu, such as insertItemAt, work only if the data model implements the MutableComboBoxModel interface (a subinterface of ComboBoxModel). Refer to the API tables to see which methods are affected.
Something else to watch out for — even for uneditable combo boxes — is ensuring that your custom model fires list data events when the combo box's data or state changes. Even immutable combo box models, whose data never changes, must fire a list data event (a CONTENTS_CHANGED event) when the selection changes. One way to get the list data event firing code for free is to make your combo box model a subclass of AbstractListModel.

Combo boxes also generate item events, which are fired when any of the items' selection state changes. Only one item at a time can be selected in a combo box, so when the user makes a new selection the previously selected item becomes unselected. Thus two item events are fired each time the user selects a different item from the menu. If the user chooses the same item, no item events are fired. Use addItemListener to register an item listener on a combo box.

Although JComboBox inherits methods to register listeners for low-level events — focus, key, and mouse events, for example — we recommend that you don't listen for low-level events on a combo box. Here's why: A combo box is a compound component — it is comprised of two or more other components. The combo box itself fires high-level events such as action events. Its subcomponents fire low-level events such as mouse, key, and focus events. The low-level events and the subcomponent that fires them are look-and-feel-dependent. To avoid writing look-and-feel-dependent code, you should listen only for high-level events on a compound component such as a combo box.

A renderer for a combo box must implement the ListCellRenderer interface. A combo box's editor must implement ComboBoxEditor.

Note that combo boxes and lists use the same type of renderer — ListCellRenderer. You can save yourself some time by sharing renderers between combo boxes and lists, if it makes sense for your program.

Every dialog is dependent on a Frame component. When that Frame is destroyed, so are its dependent Dialogs. When the frame is iconified, its dependent Dialogs also disappear from the screen. When the frame is deiconified, its dependent Dialogs return to the screen. A swing JDialog class inherits this behavior from the AWT Dialog class.

A Dialog can be modal. When a modal Dialog is visible, it blocks user input to all other windows in the program. JOptionPane creates JDialogs that are modal. To create a non-modal Dialog, you must use the JDialog class directly.

The JDialog class is a subclass of the AWT java.awt.Dialog class. It adds a root pane container and support for a default close operation to the Dialog object . These are the same features that JFrame has, and using JDialog directly is very similar to using JFrame. If you're going to use JDialog directly, then you should understand the material in Using Top-Level Containers and How to Make Frames, especially Responding to Window-Closing Events.

Even when you use JOptionPane to implement a dialog, you're still using a JDialog behind the scenes. The reason is that JOptionPane is simply a container that can automatically create a JDialog and add itself to the JDialog's content pane.

The two most useful showXxxDialog methods are showMessageDialog and showOptionDialog. The showMessageDialog method displays a simple, one-button dialog. The showOptionDialog method displays a customized dialog — it can display a variety of buttons with customized button text, and can contain a standard text message or a collection of components.

The other two showXxxDialog methods are used less often. The showConfirmDialog method asks the user to confirm something, but presents standard button text (Yes/No or the localized equivalent, for example) rather than button text customized to the user situation (Start/Cancel, for example). A fourth method, showInputDialog, is designed to display a modal dialog that gets a string from the user, using either a text field, an uneditable combo box or a list.

JOptionPane (constructor)
Creates a JOptionPane with the specified buttons, icons, message, title, and so on. You must then add the option pane to a JDialog, register a property-change listener on the option pane, and show the dialog.

Component parentComponent
The first argument to each showXxxDialog method is always the parent component, which must be a Frame, a component inside a Frame, or null. If you specify a Frame or Dialog, then the Dialog will appear over the center of the Frame and follow the focus behavior of that Frame. If you specify a component inside a Frame, then the Dialog will appear over the center of that component and will follow the focus behavior of that component's Frame. If you specify null, then the look and feel will pick an appropriate position for the dialog — generally the center of the screen — and the Dialog will not necessarily follow the focus behavior of any visible Frame or Dialog.
The JOptionPane constructors do not include this argument. Instead, you specify the parent frame when you create the JDialog that contains the JOptionPane, and you use the JDialog setLocationRelativeTo method to set the dialog position.

Object initialValue
Specifies the default value to be selected.

As the previous code snippets showed, the showMessageDialog, showConfirmDialog, and showOptionDialog methods return an integer indicating the user's choice. The values for this integer are YES_OPTION, NO_OPTION, CANCEL_OPTION, OK_OPTION, and CLOSED_OPTION. Except for CLOSED_OPTION, each option corresponds to the button the user pressed. When CLOSED_OPTION is returned, it indicates that the user closed the dialog window explicitly, rather than by choosing a button inside the option pane.

Even if you change the strings that the standard dialog buttons display, the return value is still one of the pre-defined integers. For example, a YES_NO_OPTION dialog always returns one of the following values: YES_OPTION, NO_OPTION, or CLOSED_OPTION.

If you do not care to limit the user's choices, you can either use a form of the showInputDialog method that takes fewer arguments or specify null for the array of objects. In the Java look and feel, substituting null for possibilities results in a dialog that has a text field and looks like this:

Because the user can type anything into the text field, you might want to check the returned value and ask the user to try again if it is invalid. Another approach is to create a custom dialog that validates the user-entered data before it returns.


If you're designing a custom dialog, you need to design your dialog's API so that you can query the dialog about what the user chose. For example, CustomDialog has a getValidatedText method that returns the text the user entered.


Stopping Automatic Dialog Closing

By default, when the user clicks a JOptionPane-created button, the dialog closes. But what if you want to check the user's answer before closing the dialog? In this case, you must implement your own property change listener so that when the user clicks a button, the dialog does not automatically close.
DialogDemo contains two dialogs that implement a property change listener. One of these dialogs is a custom modal dialog, implemented in CustomDialog, that uses JOptionPane both to get the standard icon and to get layout assistance. The other dialog, whose code is below, uses a standard Yes/No JOptionPane. Though this dialog is rather useless as written, its code is simple enough that you can use it as a template for more complex dialogs.

Besides setting the property change listener, the following code also calls the JDialog's setDefaultCloseOperation method and implements a window listener that handles the window close attempt properly. If you do not care to be notified when the user closes the window explicitly, then ignore the bold code.

final JOptionPane optionPane = new JOptionPane(
                "The only way to close this dialog is by\n"
                + "pressing one of the following buttons.\n"
                + "Do you understand?",

final JDialog dialog = new JDialog(frame,
                             "Click a button",
dialog.addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent we) {
        setLabel("Thwarted user attempt to close window.");
    new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent e) {
            String prop = e.getPropertyName();

            if (dialog.isVisible()
             && (e.getSource() == optionPane)
             && (prop.equals(JOptionPane.VALUE_PROPERTY))) {
                //If you were going to check something
                //before closing the window, you'd do
                //it here.

int value = ((Integer)optionPane.getValue()).intValue();
if (value == JOptionPane.YES_OPTION) {
} else if (value == JOptionPane.NO_OPTION) {
    setLabel("Try using the window decorations "
             + "to close the non-auto-closing dialog. "
             + "You can't!");
>Editor panes, by default, know how to read, write, and edit plain, HTML, and RTF text. Text panes inherit this capability but impose certain limitations. A text pane insists that its document implement the StyledDocument interface. HTMLDocument and RTFDocument are both StyledDocuments so HTML and RTF work as expected within a text pane. If you load a text pane with plain text though, the text pane's document is not a PlainDocument as you might expect, but a DefaultStyledDocument.

>TextPanes only support StyledEditorKit only
>Be aware that the read and write methods for StyleEditorKit work with plain text.
>Through the API provided in the JTextPane class, you can embed images and components in a text pane. You can embed images in an editor pane, too, but only by including the images in an HTML or RTF file.


Swing Models

>Although Swing's model architecture is sometimes referred to as a Model-View-Controller (MVC) design, it really isn't. Swing components are generally implemented so that the view and controller are indivisible, implemented by a single UI object provided by the look and feel. The Swing model architecture is more accurately described as a separable model architecture.

No comments:

Post a Comment