![]() |
|||
![]() ![]() |
![]() |
|
![]() |
Adding a Title to a Border It is often desirable to add a title to the border surrounding the components when grouping components. The BorderFactory method createTitledBorder returns an instance of a TitledBorder. This type of border can be used to add a title to any border. The text, font, position, and color of the border can be specified while obtaining the border or altered later by calling methods contained in the TitledBorder class. The title can be placed above or below the bordered component. It can also be placed above, below, or through the border. The positioning of the border is determined by two parameters that can be specified when obtaining the titled border, or through methods in the TitledBorder class. The properties for positioning the border are titlePosition and titleJustification. These constants are defined in the TitledBorder class, not in the SwingConstants class. The JFC is somewhat inconsistent about which constants are defined where. It is unfortunate that these constants werent shared with others that convey the same meaning in the SwingConstants class. Figure 5.10 demonstrates the available constants and how the title is positioned for each combination of the positioning constants.
The following code fragment obtains the handle to a TitledBorder from the BorderFactory. The word Title will be centered above the border. Figure 5.10 shows all the possible combinations of title positioning around a JLabel. Notice how the TitledBorder class requires a reference to the border that is getting the title, an etched border in the example below. Border etched = BorderFactory.createEtchedBorder();Border border = BorderFactory.createTitledBorder( etched, Title, TitledBorder.CENTER, TitledBorder.ABOVE_TOP ); Creating Your Own BorderAs was described earlier in this chapter, Border is an interface. This allows any class to implement this interface and be set as the border to any instance of a JComponent extension. This section presents three classes, two of which can be used as borders. The third class is an abstract base class for the two concrete Border classes. These borders use the Java threading mechanism to create an animated border. The first class is an abstract class named AnimatedBorder. This class extends the JFC EmptyBorder class. The EmptyBorder class manages the real estate where the border paints. This is done with the Insets for the border. EmptyBorder extends the AbstractBorder class. Many borders that you will create will extend AbstractBorder, as do most of the JFC borders. The AnimatedBorder class is presented in Listing 5.1. Its primary duty is to manage the thread used to create the animation. It contains one bound property that determines how often the animation occurs. To support the bound property, the class contains the required methods for managing PropertyChangeListeners. The run method is very simple. It sleeps the amount of time specified by the sleepTime property and then forces the border to be painted. Classes that extend AnimatedBorder perform the actual animation in their paintBorder method. Recall that paintBorder is one of the methods defined in the Border interface. This ensures that all borders will contain the paintBorder method. Listing 5.1 The AnimatedBorder Class package com.foley.borders; import java.awt.Insets; import java.awt.Component; import java.awt.Graphics; import java.awt.Color; import java.beans.PropertyChangeSupport; import java.beans.PropertyChangeListener; import javax.swing.JComponent; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; /** * AnimatedBorder is an abstract class that can be * extended to create animated borders. This class * manages the animation thread. It forces the border * to be redrawn each animation cycle. It is the * responsibility of the child class to track * which animation cycle they are drawing. * * @author Mike Foley * @see Border **/ public abstract class AnimatedBorder extends EmptyBorder implements Runnable { /** * The component this Border borders. **/ private JComponent c; /** * The delay between border paints. **/ private int sleepTime = 250; /** * Support for property change listeners, and bound * property names. **/ protected PropertyChangeSupport changes = new PropertyChangeSupport(this); public static final String SLEEP_TIME_PROPERTY = SleepTimeProperty; /** * Constructor * Create an Insets structure and call our working constructor. * * @param c The component we border. * @param top The top border width. * @param left The left border width. * @param bottom The bottom border width. * @param right The right border width. **/ public AnimatedBorder( JComponent c, int top, int left, int bottom, int right ) { this( c, new Insets( top, left, bottom, right ) ); } /** * Constructor. * Store a reference to the component we border. * Create, and start, the thread which performs * the animation. * * @param c The component we border. * @param insets The border size. **/ public AnimatedBorder( JComponent c, Insets insets ) { super( insets ); this.c = c; Thread animator = new Thread( this ); animator.start(); } /** * Set the sleep time. This is the cycle time * between animations. * This is a bound property. * * @param sleepTime The new animation cycle time. **/ public void setSleepTime( int sleepTime ) { Integer old = new Integer( this.sleepTime ); this.sleepTime = sleepTime; changes.firePropertyChange( SLEEP_TIME_PROPERTY, old, new Integer( this.sleepTime ) ); } // setSleepTime /** * @return The current cycle time. **/ public int getSleepTime() { return( this.sleepTime ); } /** * @return The component we border. **/ public JComponent getBorderedComponent() { return( c ); } /** * The animation thread. * Sleep the specified amount of time, then * repaint the bordered component. This is an * expensive way to force the border to redraw. * If the animated borders are placed around * complex components, this can be an issue. **/ public void run() { while( true ) { try { Thread.sleep( sleepTime ); // // Repaint is thread safe for Swing components. c.repaint(); } catch( InterruptedException ie ) { // Dont care if interrupted. } } } // run /** * Add the given listener to those receiving property change * notifications. * * @param l the PropertyChangeListener * @see #removePropertyChangeListener **/ public void addPropertyChangeListener( PropertyChangeListener l ) { changes.addPropertyChangeListener( l ); } // addPropertyChangeListener /** * Remove the given listener from those receiving property change * notifications. * * @param l the PropertyChangeListener * @see #addPropertyChangeListener **/ public void removePropertyChangeListener(PropertyChangeListener l) { changes.removePropertyChangeListener( l ); } // removePropertyChangeListener } // AnimatedBorder
|
![]() |
|