The API changes in Swing for Java SE 5.0 are broken down into the following sections:
This is the most visible change to Swing in 5.0. If you use the
Java look and feel your application will automatically get a new
look, called Ocean, in 5.0. Ocean was designed with compatibility
in mind so that we did not change the preferred size of any of the
widgets, only the look and a small portion of the feel has changed.
The old look can be obtained by setting the system property
swing.metalTheme=steel
.
Ocean is implemented as a custom MetalTheme
that is currently private. The advantage of this approach is that
if you have created a custom MetalTheme
you will not
be affected at all by Ocean, that is, your application will look as
it did in 1.4.
Disabled Icons for AbstractButton subclasses are now generated from the UI. This resulted in revising the specification of getDisabledIcon to:
/** * Returns the icon used by the button when it's disabled. * If no disabled icon has been set this will forward the call to * the ui to construct an appropriate disabled Icon. * <p> * Some types of look and feel might not render the disabled Icon, in which * case they will ignore this. * * @return the <code>disabledIcon</code> property * @see #getPressedIcon * @see #setDisabledIcon * @see javax.swing.plaf.ButtonUI#getDisabledIcon */ public Icon getDisabledIcon();
And adding the method getDisabledIcon
to ButtonUI.
/** * Returns the icon to display when the developer has not specified * a disabled icon. * <p> * Some look and feels might not render the disabled Icon, in which * case they will ignore this. * * @param button AbstractButton requesting the Icon * @return Disabled icon, or null. * @see javax.swing.AbstractButton#setIcon * @see javax.swing.AbstractButton#setDisabledIcon * @throws NullPointerException if <code>button</code> is null * @since 1.5 */ public Icon getDisabledIcon(AbstractButton button);
To customize the look of disabled icons for JButton MetalButtonUI
will override getDisabledIcon
.
/** * Returns the icon to display when the button is disabled. * * @param button AbstractButton requesting the Icon * @return Disabled icon, or null. * @see javax.swing.AbstractButton#setIcon * @see javax.swing.AbstractButton#setDisabledIcon * @throws NullPointerException if <code>button</code> is null * @since 1.5 */ public Icon getDisabledIcon(AbstractButton button);
To customize the look of JComboBox MetalCombBoxUI will override the following methods:
/** * If necessary paints the currently selected item. * * @param g Graphics to paint to * @param bounds Region to paint current value to * @param hasFocus whether or not the JComboBox has focus * @throws NullPointerException if any of the arguments are null. * @since 1.5 */ public void paintCurrentValue(Graphics g, Rectangle bounds, boolean hasFocus); /** * If necessary paints the background of the currently selected item. * * @param g Graphics to paint to * @param bounds Region to paint background to * @param hasFocus whether or not the JComboBox has focus * @throws NullPointerException if any of the arguments are null. * @since 1.5 */ public void paintCurrentValueBackground(Graphics g, Rectangle bounds, boolean hasFocus);
To customize the look of JButton MetalButtonUI will override the following methods:
/** * If necessary paints the background of the component, then * invokes <code>paint</code>. * * @param g Graphics to paint to * @param c JComponent painting on * @throws NullPointerException if <code>g</code> or <code>c</code> is * null * @see javax.swing.plaf.ComponentUI#update * @see javax.swing.plaf.ComponentUI#paint * @since 1.5 */ public void update(Graphics g, JComponent c);
To customize the look of JMenuBar metal will now provide MetalMenuBarUI.
To customize the look of JToolBar MetalToolBarUI
will now override update
.
/** * If necessary paints the background of the component, then invokes * <code>paint</code>. * * @param g Graphics to paint to * @param c JComponent painting on * @throws NullPointerException if <code>g</code> or <code>c</code> is * null * @see javax.swing.plaf.ComponentUI#update * @see javax.swing.plaf.ComponentUI#paint * @since 1.5 */ public void update(Graphics g, JComponent c);
To customize the look of JToggleButton MetalToggleButtonUI will now override the following methods:
/** * If necessary paints the background of the component, then invokes * <code>paint</code>. * * @param g Graphics to paint to * @param c JComponent painting on * @throws NullPointerException if <code>g</code> or <code>c</code> is * null * @see javax.swing.plaf.ComponentUI#update * @see javax.swing.plaf.ComponentUI#paint * @since 1.5 */ public void update(Graphics g, JComponent c); /** * Paints the appropriate icon of the button <code>b</code> in the * space <code>iconRect</code>. * * @param g Graphics to paint to * @param b Button to render for * @param iconRect space to render in * @throws NullPointerException if any of the arguments are null. * @since 1.5 */ protected void paintIcon(Graphics g, AbstractButton b, Rectangle iconRect); /** * Returns the icon to display when the button is disabled. * * @param button AbstractButton requesting the Icon * @return Disabled icon, or null. * @see javax.swing.AbstractButton#setIcon * @see javax.swing.AbstractButton#setDisabledIcon * @throws NullPointerException if <code>button</code> is null * @since 1.5 */ public Icon getDisabledIcon(AbstractButton button);
One of Swing's early design goals was the ability for an application to support a multitude of look and feels without changing code. This feature allows developers to seamlessly run their applications with numerous look and feels. While there have been a handful of custom look and feels, most notably the Alloy Look and Feel, creating a new look and feel requires programming and an extensive knowledge of Swing's pluggable look-and-feel architecture, limiting this feature mostly to experts. In 5.0, a skinnable look and feel, named Synth, has been added to Swing which can be completely customized without writing code, enabling even non-programmers to create new look and feels.
Synth lives in the javax.swing.plaf.synth package. The package level javadoc gives a brief overview of Synth. Synth can be customized by way of a file. To enable Synth to extend javax.swing.plaf.basic the following changes were made:
The following methods were unnecessary (implementation identical to that of the superclass) and have been removed: BasicOptionPaneUI's getMinimumSize BasicOptionPaneUI's getMaximumSize BasicTabbedPaneUI's getPreferredSize BasicMenuBarUI's getPreferredSize BasicPopupMenuUI's getMinimumSize BasicPopupMenuUI's getPreferredSize BasicPopupMenuUI's getMaximumSize BasicScrollPaneUI's getPreferredSize BasicScrollPaneUI's getMinimumSize BasicListUI's getMinimumSize BasicListUI's getMaximumSize BasicScrollBarUI's getMinimumSize BasicToolBarSeparatorUI's getMinimumSize BasicToolBarSeparatorUI's getMaximumSize BasicToolBarUI's getMinimumSize BasicToolBarUI's getPreferredSize BasicToolBarUI's getMaximumSize.
Many of the JComponent subclasses have primitive properties. As the UIs need to install a value for these properties they have no way to determine if the property was set by the developer and may end up resetting the value a developer has specified. To enable the UI to only set a value if the developer hasn't specified we will route all primitive setters through a method in LookAndFeel:
/** * Convenience method for installing a property with the specified name * and value on a component if that property has not already been set * by the client program. This method is intended to be used by * UI delegate instances that need to specify a default value for a * property of primitive type (boolean, int, ..), but do not wish * to override a value set by the client. Since primitive property * values cannot be wrapped with the UIResource marker, this method * uses private state to determine whether the property has been set * by the client. * @throws IllegalArgumentException if the specified property is not * one which can be set using this method * @throws ClassCastException May be thrown if the propertyValue is not * of the expected type. * @throws NullPointerException May be thrown if the JComponent is null, * or the propertyValue is null. * @param c the target component for installing the property * @param propertyName String containing the name of the property to be set * @param propertyValue Object containing the value of the property * @since 1.5 */ public static void installProperty(JComponent c, String propertyName, Object propertyValue)
To allow subclasses of BasicTabbedPaneUI to create their own buttons the following method was added:
/** * Creates and returns a JButton that will provide the user * with a way to scroll the tabs in a particular direction. The * returned JButton must be instance of UIResource. * * @param direction One of the SwingConstants constants: * SOUTH, NORTH, EAST or WEST * @return Widget for user to * @see javax.swing.JTabbedPane#setTabPlacement * @see javax.swing.SwingConstants * @throws IllegalArgumentException if direction is not one of * NORTH, SOUTH, EAST or WEST * @since 1.5 */ protected JButton createScrollButton(int direction);
To allow subclasses of BasicTabbedPaneUI to determine which tab has focus the following was added:
/** * Returns the index of the tab that has focus. * * @return index of tab that has focus * @since 1.5 */ protected int getFocusIndex();
To allow subclasses of BasicTabbedPaneUI to provide a rollover effect the following was added:
/** * Sets the tab the mouse is currently over toindex
. *index
will be -1 if the mouse is no longer over any * tab. No checking is done to ensure the passed in index identifies a * valid tab. * * @param index Index of the tab the mouse is over. * @since 1.5 */ protected void setRolloverTab(int index); /** * Returns the tab the mouse is currently over, or -1 if the mouse is no * longer over any tab. * * @param index Index of the tab the mouse is over. * @since 1.5 */ protected int getRolloverTab();
The following field was added to BasicColorChooserUI:
/** * JColorChooser this BasicColorChooserUI is installed on. * * @since 1.5 */ protected JColorChooser chooser;
To allow BasicSpinnerUI subclasses to install their own keyboard actions the following method was added:
/** * Installs the keyboard Actions onto the JSpinner. * * @since 1.5 */ protected void installKeyboardActions();
To allow BasicSpinnerUI subclasses to provide their own spin buttons the following methods were added:
/** * Installs the necessary listeners on the next button,c
, * to update theJSpinner
in response to a user gesture. * * @param c Component to install the listeners on * @throws NullPointerException ifc
is null. * @see #createNextButton * @since 1.5 */ protected void installNextButtonListeners(Component c); /** * Installs the necessary listeners on the previous button,c
, * to update theJSpinner
in response to a user gesture. * * @param c Component to install the listeners on. * @throws NullPointerException ifc
is null. * @see #createPreviousButton * @since 1.5 */ protected void installPreviousButtonListeners(Component c);
To allow subclasses of BasicScrollBarUI to provide rollover feedback the following method were added:
/** * Sets whether or not the mouse is currently over the thumb. * * @param active True indicates the thumb is currently active. * @since 1.5 */ protected void setThumbRollover(boolean active); /** * Returns true if the mouse is currently over the thumb. * * @return true if the thumb is currently active * @since 1.5 */ public boolean isThumbRollover(); /** * Indicates whether the user can absolutely position the thumb with * a mouse gesture (usually the middle mouse button). * * @return true if a mouse gesture can absolutely position the thumb * @since 1.5 */ public boolean getSupportsAbsolutePositioning();
To cut down on class loads the following was added to BasicComboPopup:
/** * Gets the AccessibleContext associated with this BasicComboPopup. * The AccessibleContext will have its parent set to the ComboBox. * * @return an AccessibleContext for the BasicComboPopup * @since 1.5 */ public AccessibleContext getAccessibleContext();
To enable subclasses of BasicSplitPaneDivider to provide mouse over feedback the following was added:
/** * Sets whether or not the mouse is currently over the divider. * * @param mouseOver whether or not the mouse is currently over the divider * @since 1.5 */ protected void setMouseOver(boolean mouseOver); /** * Returns whether or not the mouse is currently over the divider * * @param Returns whether or not the mouse is currently over the divider */ public boolean isMouseOver();
To allow subclasses of BasicTreeUI to alter the location of a particular row the following had been added:
/** * Returns the location, along the x-axis, to render a particular row * at. The return value does not include any Insets specified on the JTree. * This does not check for the validity of the row or depth, it is assumed * to be correct and will not throw an Exception if the row or depth * doesn't match that of the tree. * * @param row Row to return x location for * @param depth Depth of the row * @return amount to indent the given row. * @since 1.5 */ protected int getRowX(int row, int depth);
To allow subclasses of BasicProgressBarUI to alter the size of the progress bar the following was added:
/** * Used to hold the location and size of the bouncing box (returned * by getBox) to be painted. * * @since 1.5 */ protected Rectangle boxRect; /** * Returns the length * of the "bouncing box" to be painted. * This method is invoked by the * default implementation of <code>paintIndeterminate</code> * to get the width (if the progress bar is horizontal) * or height (if vertical) of the box. * For example: * <blockquote> * <pre> *boxRect.width = getBoxLength(componentInnards.width, * componentInnards.height); * </pre> * </blockquote> * * @param availableLength the amount of space available * for the bouncing box to move in; * for a horizontal progress bar, * for example, * this should be * the inside width of the progress bar * (the component width minus borders) * @param otherDimension for a horizontal progress bar, this should be * the inside height of the progress bar; this * value might be used to constrain or determine * the return value * * @return the size of the box dimension being determined; * must be no larger than <code>availableLength</code> * * @see javax.swing.SwingUtilities#calculateInnerArea * @since 1.5 */ protected int getBoxLength(int availableLength, int otherDimension);
To enable subclasses of BasicSliderUI to specialize painting based on the state of the slider the following was added:
/** * Returns true if the user is dragging the slider. * * @return true if the user is dragging the slider * @since 1.5 */ protected boolean isDragging();
To allow subclasses of BasicToolBarUI to specialize how the window used for dragging is painted the following was added:
/**
* Paints the contents of the window used for dragging.
*
* @param g Graphics to paint to.
* @throws NullPointerException is g
is null
* @since 1.5
*/
protected void paintDragWindow(Graphics g);
To allow subclasses of BasicDesktopIconUI to get a handle to the iconPane the following was added:
/** * The title pane component used in the desktop icon. * * @since 1.5 */ protected JComponent iconPane;
JPopupMenu allows
for creating a popup menu. Prior to 5.0, developers using a
JPopupMenu
would have to install the necessary
listeners and register the appropriate key bindings to show the
JPopupMenu
. In 5.0 we added a mechanism to take care
of registering the appropriate listeners and key bindings. This
resulted in the following methods being added to JComponent:
/** * Sets whether or not <code>getComponentPopupMenu</code> should delegate * to the parent if this component does not have a <code>JPopupMenu</code> * assigned to it. * <p> * The default value for this is false, but some <code>JComponent</code> * subclasses that are implemented as a number of <code>JComponent</code>s * may set this to true. * <p> * This is a bound property. * * @param value whether or not the JPopupMenu is inherited * @see #setComponentPopupMenu * @beaninfo * bound: true * description: Whether or not the JPopupMenu is inherited * @since 1.5 */ public void setInheritsPopupMenu(boolean value); /** * Returns true if the JPopupMenu should be inherited from the parent. * * @see #setComponentPopupMenu * @since 1.5 */ public boolean getInheritsPopupMenu(); /** * Sets the <code>JPopupMenu</code> for this <code>JComponent</code>. * The UI is responsible for registering bindings and adding the necessary * listeners such that the <code>JPopupMenu</code> will be shown at * the appropriate time. When the <code>JPopupMenu</code> is shown * depends upon the look and feel: some may show it on a mouse event, * some may enable a key binding. * <p> * If <code>popup</code> is null, and <code>getInheritsPopupMenu</code> * returns true, then <code>getComponentPopupMenu</code> will be delegated * to the parent. This provides for a way to make all child components * inherit the popupmenu of the parent. * <p> * This is a bound property. * * @param popup - the popup that will be assigned to this component * may be null * @see #getComponentPopupMenu * @beaninfo * bound: true * preferred: true * description: Popup to show * @since 1.5 */ public void setComponentPopupMenu(JPopupMenu popup); /** * Returns <code>JPopupMenu</code> that assigned for this component. * If this component does not have a <code>JPopupMenu</code> assigned * to it and <code>getInheritsPopupMenu</code> is true, this * will return <code>getParent().getComponentPopupMenu()</code> (assuming * the parent is valid.) * * @return <code>JPopupMenu</code> assigned for this component * or <code>null</code> if no popup assigned * @see #setComponentPopupMenu * @since 1.5 */ public JPopupMenu getComponentPopupMenu();
The following was added to BasicLookAndFeel:
/** * UIManager.setLookAndFeel calls this method before the first call * (and typically the only call) to getDefaults(). * * @since 1.5 */ public void initialize() { /** * UIManager.setLookAndFeel calls this method just * before we're replaced by a new default look and feel. * * @since 1.5 */ public void uninitialize() {
Synopsis says it all. The following has been added to
JTable
:
/** * Printing modes, used in printing <code>JTable</code>s. * * @see #print(JTable.PrintMode, MessageFormat, MessageFormat, * boolean, PrintRequestAttributeSet, boolean) * @see #getPrintable * @since 1.5 */ public enum PrintMode { /** * Printing mode that prints the table at its current size, * spreading both columns and rows across multiple pages if necessary. */ NORMAL, /** * Printing mode that scales the output smaller, if necessary, * to fit the table's entire width (and thereby all columns) on each page; * Rows are spread across multiple pages as necessary. */ FIT_WIDTH } /** * A convenience method that displays a printing dialog, and then prints * this <code>JTable</code> in mode <code>PrintMode.FIT_WIDTH</code>, * with no header or footer text. A modal progress dialog, with an abort * option, will be shown for the duration of printing. * <p> * Note: In headless mode, no dialogs will be shown. * * @return true, unless printing is cancelled by the user * @throws PrinterException if an error in the print system causes the job * to be aborted * @see #print(JTable.PrintMode, MessageFormat, MessageFormat, * boolean, PrintRequestAttributeSet, boolean) * @see #getPrintable * * @since 1.5 */ public boolean print() throws PrinterException; /** * A convenience method that displays a printing dialog, and then prints * this <code>JTable</code> in the given printing mode, * with no header or footer text. A modal progress dialog, with an abort * option, will be shown for the duration of printing. * <p> * Note: In headless mode, no dialogs will be shown. * * @param printMode the printing mode that the printable should use * @return true, unless printing is cancelled by the user * @throws PrinterException if an error in the print system causes the job * to be aborted * @see #print(JTable.PrintMode, MessageFormat, MessageFormat, * boolean, PrintRequestAttributeSet, boolean) * @see #getPrintable * * @since 1.5 */ public boolean print(PrintMode printMode) throws PrinterException; /** * A convenience method that displays a printing dialog, and then prints * this <code>JTable</code> in the given printing mode, * with the specified header and footer text. A modal progress dialog, * with an abort option, will be shown for the duration of printing. * <p> * Note: In headless mode, no dialogs will be shown. * * @param printMode the printing mode that the printable should use * @param headerFormat a <code>MessageFormat</code> specifying the text * to be used in printing a header, * or null for none * @param footerFormat a <code>MessageFormat</code> specifying the text * to be used in printing a footer, * or null for none * @return true, unless printing is cancelled by the user * @throws PrinterException if an error in the print system causes the job * to be aborted * @see #print(JTable.PrintMode, MessageFormat, MessageFormat, * boolean, PrintRequestAttributeSet, boolean) * @see #getPrintable * * @since 1.5 */ public boolean print(PrintMode printMode, MessageFormat headerFormat, MessageFormat footerFormat) throws PrinterException; /** * Print this <code>JTable</code>. Takes steps that the majority of * developers would take in order to print a <code>JTable</code>. * In short, it prepares the table, calls <code>getPrintable</code> to * fetch an appropriate <code>Printable</code>, and then sends it to the * printer. * <p> * A <code>boolean</code> parameter allows you to specify whether or not * a printing dialog is displayed to the user. When it is, the user may * use the dialog to change printing attributes or even cancel the print. * Another parameter allows for printing attributes to be specified * directly. This can be used either to provide the initial values for the * print dialog, or to supply any needed attributes when the dialog is not * shown. * <p> * A second <code>boolean</code> parameter allows you to specify whether * or not to perform printing in an interactive mode. If <code>true</code>, * a modal progress dialog, with an abort option, is displayed for the * duration of printing . This dialog also prevents any user action which * may affect the table. However, it can not prevent the table from being * modified by code (for example, another thread that posts updates using * <code>SwingUtilities.invokeLater</code>). It is therefore the * responsibility of the developer to ensure that no other code modifies * the table in any way during printing (invalid modifications include * changes in: size, renderers, or underlying data). Printing behavior is * undefined when the table is changed during printing. * <p> * If <code>false</code> is specified for this parameter, no dialog will * be displayed and printing will begin immediately on the event-dispatch * thread. This blocks any other events, including repaints, from being * processed until printing is complete. Although this effectively prevents * the table from being changed, it doesn't provide a good user experience. * For this reason, specifying <code>false</code> is only recommended when * printing from an application with no visible GUI. * <p> * Note: Attempting to show the printing dialog or run interactively, while * in headless mode, will result in a <code>HeadlessException</code>. * <p> * Before fetching the printable, this method prepares the table in order * to get the most desirable printed result. If the table is currently * in an editing mode, it terminates the editing as gracefully as * possible. It also ensures that the table's current selection and * focused cell are not indicated in the printed output. This is handled on * the view level, and only for the duration of the printing, thus no * notification needs to be sent to the selection models. * <p> * See {@link #getPrintable} for further description on how the * table is printed. * * @param printMode the printing mode that the printable should use * @param headerFormat a <code>MessageFormat</code> specifying the text * to be used in printing a header, * or null for none * @param footerFormat a <code>MessageFormat</code> specifying the text * to be used in printing a footer, * or null for none * @param showPrintDialog whether or not to display a print dialog * @param attr a <code>PrintRequestAttributeSet</code> * specifying any printing attributes, * or null for none * @param interactive whether or not to print in an interactive mode * @return true, unless printing is cancelled by the user * @throws PrinterException if an error in the print system causes the job * to be aborted * @throws HeadlessException if the method is asked to show a printing * dialog or run interactively, and * <code>GraphicsEnvironment.isHeadless</code> * returns true * @see #getPrintable * @see java.awt.GraphicsEnvironment#isHeadless * * @since 1.5 */ public boolean print(PrintMode printMode, MessageFormat headerFormat, MessageFormat footerFormat, boolean showPrintDialog, PrintRequestAttributeSet attr, boolean interactive) throws PrinterException, HeadlessException; /** * Return a <code>Printable</code> for use in printing this JTable. * <p> * The <code>Printable</code> can be requested in one of two printing modes. * In both modes, it spreads table rows naturally in sequence across * multiple pages, fitting as many rows as possible per page. * <code>PrintMode.NORMAL</code> specifies that the table be * printed at its current size. In this mode, there may be a need to spread * columns across pages in a similar manner to that of the rows. When the * need arises, columns are distributed in an order consistent with the * table's <code>ComponentOrientation</code>. * <code>PrintMode.FIT_WIDTH</code> specifies that the output be * scaled smaller, if necessary, to fit the table's entire width * (and thereby all columns) on each page. Width and height are scaled * equally, maintaining the aspect ratio of the output. * <p> * The <code>Printable</code> heads the portion of table on each page * with the appropriate section from the table's <code>JTableHeader</code>, * if it has one. * <p> * Header and footer text can be added to the output by providing * <code>MessageFormat</code> arguments. The printing code requests * Strings from the formats, providing a single item which may be included * in the formatted string: an <code>Integer</code> representing the current * page number. * <p> * You are encouraged to read the documentation for * <code>MessageFormat</code> as some characters, such as single-quote, * are special and need to be escaped. * <p> * Here's an example of creating a <code>MessageFormat</code> that can be * used to print "Duke's Table: Page - " and the current page number: * <p> * <pre> * // notice the escaping of the single quote * // notice how the page number is included with "{0}" * MessageFormat format = new MessageFormat("Duke''s Table: Page - {0}"); * </pre> * <p> * The <code>Printable</code> constrains what it draws to the printable * area of each page that it prints. Under certain circumstances, it may * find it impossible to fit all of a page's content into that area. In * these cases the output may be clipped, but the implementation * makes an effort to do something reasonable. Here are a few situations * where this is known to occur, and how they may be handled by this * particular implementation: * <ul> * <li>In any mode, when the header or footer text is too wide to fit * completely in the printable area -- print as much of the text as * possible starting from the beginning, as determined by the table's * <code>ComponentOrientation</code>. * <li>In any mode, when a row is too tall to fit in the * printable area -- print the upper-most portion of the row * and paint no lower border on the table. * <li>In <code>PrintMode.NORMAL</code> when a column * is too wide to fit in the printable area -- print the center * portion of the column and leave the left and right borders * off the table. * </ul> * <p> * It is entirely valid for this <code>Printable</code> to be wrapped * inside another in order to create complex reports and documents. You may * even request that different pages be rendered into different sized * printable areas. The implementation must be prepared to handle this * (possibly by doing its layout calculations on the fly). However, * providing different heights to each page will likely not work well * with <code>PrintMode.NORMAL</code> when it has to spread columns * across pages. * <p> * It is important to note that this <code>Printable</code> prints the * table at its current visual state, using the table's existing renderers. * <i>Before</i> calling this method, you may wish to <i>first</i> modify * the state of the table (such as to change the renderers, cancel editing, * or hide the selection). * <p> * You must not, however, modify the table in any way <i>after</i> * this <code>Printable</code> is fetched (invalid modifications include * changes in: size, renderers, or underlying data). The behavior of the * returned <code>Printable</code> is undefined once the table has been * changed. * <p> * Here's a simple example that calls this method to fetch a * <code>Printable</code>, shows a cross-platform print dialog, and then * prints the <code>Printable</code> unless the user cancels the dialog: * <p> * <pre> * // prepare the table for printing here first (for example, hide selection) * * // wrap in a try/finally so table can be restored even if something fails * try { * // fetch the printable * Printable printable = table.getPrintable(JTable.PrintMode.FIT_WIDTH, * new MessageFormat("My Table"), * new MessageFormat("Page - {0}")); * * // fetch a PrinterJob * PrinterJob job = PrinterJob.getPrinterJob(); * * // set the Printable on the PrinterJob * job.setPrintable(printable); * * // create an attribute set to store attributes from the print dialog * PrintRequestAttributeSet attr = new HashPrintRequestAttributeSet(); * * // display a print dialog and record whether or not the user cancels it * boolean printAccepted = job.printDialog(attr); * * // if the user didn't cancel the dialog * if (printAccepted) { * // do the printing (may need to handle PrinterException) * job.print(attr); * } * } finally { * // restore the original table state here (for example, restore selection) * } * </pre> * * @param printMode the printing mode that the printable should use * @param headerFormat a <code>MessageFormat</code> specifying the text to * be used in printing a header, or null for none * @param footerFormat a <code>MessageFormat</code> specifying the text to * be used in printing a footer, or null for none * @return a <code>Printable</code> for printing this JTable * @see Printable * @see PrinterJob * * @since 1.5 */ public Printable getPrintable(PrintMode printMode, MessageFormat headerFormat, MessageFormat footerFormat);
Some of Swing's text component methods are thread safe;
particularly those that modify the content of the text component.
Prior to 5.0 the location of the caret would only be updated if the
modification happens on the event dispatching thread. In certain
situations it is desirable to update the location regardless of
what thread the modification happens on. In order to accomodate
this the updatePolicy
property was added to DefaultCaret.
This property allows the developer to specify when the location
should change when the content changes. For backward compatibility
the policy is still to only update the location if the modification
happens on the event dispatching thread.
The results in the following fields and methods being added to DefaultCaret.
/** * Indicates that the caret position is to be updated only when * document changes are performed on the Event Dispatching Thread. * @see #setUpdatePolicy * @see #getUpdatePolicy * @since 1.5 */ public static final int UPDATE_WHEN_ON_EDT = 0; /** * Indicates that the caret should remain at the same * absolute position in the document regardless of any document * updates, except when the document length becomes less than * the current caret position due to removal. In that case the caret * position is adjusted to the end of the document. * * @see #setUpdatePolicy * @see #getUpdatePolicy * @since 1.5 */ public static final int NEVER_UPDATE = 1; /** * Indicates that the caret position is to be <b>always</b> * updated accordingly to the document changes regardless whether * the document updates are performed on the Event Dispatching Thread * or not. * * @see #setUpdatePolicy * @see #getUpdatePolicy * @since 1.5 */ public static final int ALWAYS_UPDATE = 2; /** * Sets the caret movement policy on the document updates. Normally * the caret updates its absolute position within the document on * insertions occurred before or at the caret position and * on removals before the caret position. 'Absolute position' * means here the position relative to the start of the document. * For example if * a character is typed within editable text component it is inserted * at the caret position and the caret moves to the next absolute * position within the document due to insertion and if * <code>BACKSPACE</code> is typed then caret decreases its absolute * position due to removal of a character before it. Sometimes * it may be useful to turn off the caret position updates so that * the caret stays at the same absolute position within the * document position regardless of any document updates. * <p> * The following update policies are allowed: * <ul> * <li><code>NEVER_UPDATE</code>: the caret stays at the same * absolute position in the document regardless of any document * updates, except when document length becomes less than * the current caret position due to removal. In that case caret * position is adjusted to the end of the document. * The caret doesn't try to keep itself visible by scrolling * the associated view when using this policy. </li> * <li><code>ALWAYS_UPDATE</code>: the caret always tracks document * changes. For regular changes it increases its position * if an insertion occurs before or at its current position, * and decreases position if a removal occurs before * its current position. For undo/redo updates it is always * moved to the position where update occurred. The caret * also tries to keep itself visible by calling * <code>adjustVisibility</code> method.</li> * <li><code>UPDATE_WHEN_ON_EDT</code>: acts like <code>ALWAYS_UPDATE</code> * if the document updates are performed on the Event Dispatching Thread * and like <code>NEVER_UPDATE</code> if updates are performed on * other thread. </li> * </ul> <p> * The default property value is <code>UPDATE_WHEN_ON_EDT</code>. * * @param policy one of the following values : <code>UPDATE_WHEN_ON_EDT</code>, * <code>NEVER_UPDATE</code>, <code>ALWAYS_UPDATE</code> * @throws IllegalArgumentException if invalid value is passed * * @see #getUpdatePolicy * @see #adjustVisibility * @see #UPDATE_WHEN_ON_EDT * @see #NEVER_UPDATE * @see #ALWAYS_UPDATE * * @since 1.5 */ public void setUpdatePolicy(int policy) /** * Gets the caret movement policy on document updates. * * @return one of the following values : <code>UPDATE_WHEN_ON_EDT</code>, * <code>NEVER_UPDATE</code>, <code>ALWAYS_UPDATE</code> * * @see #getUpdatePolicy * @see #UPDATE_WHEN_ON_EDT * @see #NEVER_UPDATE * @see #ALWAYS_UPDATE * * @since 1.5 */ public int getUpdatePolicy()
JEditorPane
can be used to display HTML text. When
a user clicks on a link an event is generated the allows the
developer to customize what will happen. Currently if a HTML page
has forms in it and the user triggers a submission the post happens
automatically without allowing the developer to alter the behavior.
To allow developers to customize the behavior the following methods
have been added to HTMLEditorKit:
/** * Indicates whether an html form submission is processed automatically * or only <code>FormSubmitEvent</code> is fired. * * @return true if html form submission is processed automatically, * false otherwise. * * @see #setAutoFormSubmission * @since 1.5 */ public boolean isAutoFormSubmission(); /** * Specifies if an html form submission is processed * automatically or only <code>FormSubmitEvent</code> is fired. * By default it the property is set to true. * * @see #isAutoFormSubmission * @see FormSubmitEvent * @since 1.5 */ public void setAutoFormSubmission(boolean isAuto);
A crucial part of this work was making the class
FormSubmitEvent
public, refer to 4954126 for details on this.
There is currently no way to determine if the caret in active
and blinking. The isVisible
method was intended for
this purpose, but the implementation returns whether the caret is
painted at the moment it is invoked, i.e. if the caret is blinking
isVisible
changes between true and false as the caret
blinks. To maintain backward compatibility the interpretation of
the isVisible
method has been left the same, and an
isActive
property was added that tells if the caret is
active but not necessarily visible at the time the method is
invoked.
The following methods have been added to DefaultCaret:
/** * Determines if the caret is currently active. * <p> * This method returns whether or not the <code>Caret</code> * is currently in a blinking state. It does not provide * information as to whether it is currently blinked on or off. * To determine if the caret is currently painted use the * <code>isVisible</code> method. * * @return <code>true</code> if active else <code>false</code> * @see #isVisible * * @since 1.5 */ public boolean isActive() * Sets the caret visibility, and repaints the caret. * It is important to understand the relationship between this method, * <code>isVisible</code> and <code>isActive</code>. * Calling this method with a value of <code>true</code> activates the * caret blinking. Setting it to <code>false</code> turns it completely off. * To determine whether the blinking is active, you should call * <code>isActive</code>. In effect, <code>isActive</code> is an * appropriate corresponding "getter" method for this one. * <code>isVisible</code> can be used to fetch the current * visibility status of the caret, meaning whether or not it is currently * painted. This status will change as the caret blinks on and off. * <p> * Here's a list showing the potential return values of both * <code>isActive</code> and <code>isVisible</code> * after calling this method: * <p> * <b><code>setVisible(true)</code></b>: * <ul> * <li>isActive(): true</li> * <li>isVisible(): true or false depending on whether * or not the caret is blinked on or off</li> * </ul> * <p> * <b><code>setVisible(false)</code></b>: * <ul> * <li>isActive(): false</li> * <li>isVisible(): false</li> * </ul> * * @param e the visibility specifier * @see #isActive * @see Caret#setVisible */ public void setVisible(boolean e)
The documentation for DefaultCaret's isVisible method has been updated to indicate the distinction between the two properties:
/** * Indicates whether or not the caret is currently visible. As the * caret flashes on and off the return value of this will change * between true, when the caret is painted, and false, when the * caret is not painted. <code>isActive</code> indicates whether * or not the caret is in a blinking state, such that it <b>can</b> * be visible, and <code>isVisible</code> indicates whether or not * the caret <b>is</b> actually visible. * <p> * Subclasses that wish to render a different flashing caret * should override paint and only paint the caret if this method * returns true. * * @return true if visible else false * @see Caret#isVisible * @see #isActive */ public boolean isVisible()
The background attribute from css style sheet is ignored when rendering HTML text. To get this to work we added the following method to LabelView:
/** * Sets the background color for the view. This method is typically * invoked as part of configuring this <code>View</code>. If you need * to customize the background color you should override * <code>setPropertiesFromAttributes</code> and invoke this method. A * value of null indicates no background should be rendered, so that the * background of the parent <code>View</code> will show through. * * @param bg background color, or null * @see #setPropertiesFromAttributes * @since 1.5 */ protected void setBackground(Color bg);
The TabSet does not
override the equals
method, which causes comparisons
to fail if the TabStop
array does contain the same
TabStop
s. It causes AttributeSet
not to
be equal, even though the only difference is another object
instance of TabSet
.
TabSet
will now override equals
and
hashCode
:
/** * Indicates whether this <code>TabSet</code> is equal to another one. * @param o the <code>TabSet</code> instance which this instance * should be compared to. * @return <code>true</code> if <code>o</code> is the instance of * <code>TabSet</code>, has the same number of <code>TabStop</code>s * and they are all equal, <code>false</code> otherwise. * * @since 1.5 */ public boolean equals(Object o) /** * Returns a hashcode for this set of TabStops. * @return a hashcode value for this set of TabStops. * * @since 1.5 */ public int hashCode()
Invoking JTextArea.setEditable resets the focus traversal keys. This is problmatic for developers that want to provide a custom set of focus traversal keys and conditionally change the editable property.
To fix this JComponent
now overrides the
following:
/** * Sets the focus traversal keys for a given traversal operation for this * Component. * Refer to * {@link java.awt.Component#setFocusTraversalKeys} * for a complete description of this method. * * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS * @param keystrokes the Set of AWTKeyStroke for the specified operation * @see java.awt.KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS * @see java.awt.KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS * @see java.awt.KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS * @throws IllegalArgumentException if id is not one of * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or if keystrokes * contains null, or if any Object in keystrokes is not an * AWTKeyStroke, or if any keystroke represents a KEY_TYPED event, * or if any keystroke already maps to another focus traversal * operation for this Component * @since 1.5 * @beaninfo * bound: true */ public void setFocusTraversalKeys(int id, Set keystrokes);
As requested FormSubmitEvent is not public.
ListDataEvent's constructor has been changed to swap the two indices it is passed so that the return value from getIndex0() is always <= the return value from getIndex1.
/** * Constructs a ListDataEvent object. If index0 is > * index1, index0 and index1 will be swapped such that * index0 will always be <= index1. * * @param source the source Object (typically <code>this</code>) * @param type an int specifying {@link #CONTENTS_CHANGED}, * {@link #INTERVAL_ADDED}, or {@link #INTERVAL_REMOVED} * @param index0 one end of the new interval * @param index1 the other end of the new interval */ public ListDataEvent(Object source, int type, int index0, int index1) {
JTable and JList currently provide no way to make discontinuous selections using the keyboard. To enable this the following was added to DefaultListSelectionModel:
/** * Set the lead selection index, leaving all selection values unchanged. * If leadAnchorNotificationEnabled is true, send a notification covering * the old and new lead cells. * * @param leadIndex the new lead selection index * * @see #setAnchorSelectionIndex * @see #setLeadSelectionIndex * @see #getLeadSelectionIndex * * @since 1.5 */ public void moveLeadSelectionIndex(int leadIndex)
Additionally DefaultListSelectionModel's
isLeadAnchorNotificationEnabled and
changeSelection
methods were revised.
The following static fields are now static final: JDesktopPane.LIVE_DRAG_MODE, JDesktopPane.OUTLINE_DRAG_MODE and DTD.FILE_VERSION.
Bevel borders interchange their shadowInner
and
shadowOuter
colors depending on whether they are
raised or lowered. However, the BorderFactory and BevelBorder don't
say this - it's written for a raised bevel border only. This
resulted in adding the following to
BevelBorder's constructor and
BorderFactory's createBevelBorder method:
* Note: The shadow inner and outer colors are * switched for a lowered bevel border.
/** * Overridden to return true so that any calls to <code>revalidate</code> * on any descendants of this <code>JScrollPane</code> will cause the * entire tree beginning with this <code>JScrollPane</code> to be * validated. * * @return true * @see java.awt.Container#validate * @see JComponent#revalidate * @see JComponent#isValidateRoot * * @beaninfo * hidden: true */
The PropertyChangeSupport
class is a utility that makes it easy to register and fire PropertyChangeEvents
- which is a notification that a JavaBean property has been
modified.
SwingPropertyChangeSupport is a subclass of
PropertyChangeSupport
and has a lot of redundant
methods. Furthermore, in the 1.2 timeframe, support for property
changes was added to Component. Rather
than introduce a dependency on
SwingPropertyChangeSupport
, Component
uses PropertyChangeSupport
. JComponent
maintains an instance of SwingPropertyChangeSupport
and Component
maintains an instance of
PropertyChangeSupport
. The results is every
JComponent
having two instances of
PropertyChangeSupport
- one of which is dormant. To
cut down on the overlap between Component
and
JComponent
as well as
PropertyChangeSupport
and
SwingPropertyChangeSupport
the following changes were
made:
Promote the following methods from JComponent
to
Component
:
/** * Reports a bound property change. * * @param propertyName the programmatic name of the property * that was changed * @param oldValue the old value of the property (as a byte) * @param newValue the new value of the property (as a byte) * @see #firePropertyChange(java.lang.String, java.lang.Object, * java.lang.Object) * @since 1.5 */ public void firePropertyChange(String propertyName, byte oldValue, byte newValue); /** * Reports a bound property change. * * @param propertyName the programmatic name of the property * that was changed * @param oldValue the old value of the property (as a char) * @param newValue the new value of the property (as a char) * @see #firePropertyChange(java.lang.String, java.lang.Object, * java.lang.Object) * @since 1.5 */ public void firePropertyChange(String propertyName, char oldValue, char newValue); /** * Reports a bound property change. * * @param propertyName the programmatic name of the property * that was changed * @param oldValue the old value of the property (as a short) * @param newValue the old value of the property (as a short) * @see #firePropertyChange(java.lang.String, java.lang.Object, * java.lang.Object) * @since 1.5 */ public void firePropertyChange(String propertyName, short oldValue, short newValue); /** * Reports a bound property change. * * @param propertyName the programmatic name of the property * that was changed * @param oldValue the old value of the property (as a long) * @param newValue the new value of the property (as a long) * @see #firePropertyChange(java.lang.String, java.lang.Object, * java.lang.Object) * @since 1.5 */ public void firePropertyChange(String propertyName, long oldValue, long newValue); /** * Reports a bound property change. * * @param propertyName the programmatic name of the property * that was changed * @param oldValue the old value of the property (as a float) * @param newValue the new value of the property (as a float) * @see #firePropertyChange(java.lang.String, java.lang.Object, * java.lang.Object) * @since 1.5 */ public void firePropertyChange(String propertyName, float oldValue, float newValue); /** * Reports a bound property change. * * @param propertyName the programmatic name of the property * that was changed * @param oldValue the old value of the property (as a double) * @param newValue the new value of the property (as a double) * @see #firePropertyChange(java.lang.String, java.lang.Object, * java.lang.Object) * @since 1.5 */ public void firePropertyChange(String propertyName, double oldValue, double newValue);
The corresponding methods in JComponent
have been
removed.
All the methods from SwingPropertyChangeSupport
have been removed, only the constructor remains.
Swing's cell rendenders override a handful of methods to do nothing as they are not needed for cell renderers. They should override a couple of methods that are now being called to do nothing.
The following methods were added to DefaultTableCellRenderer, DefaultListCellRenderer and DefaultTreeCellRenderer
/** * Overridden for performance reasons. * See the <a href="#override">Implementation Note</a> * for more information. * * @since 1.5 */ public void invalidate(); /** * Overridden for performance reasons. * See the <a href="#override">Implementation Note</a> * for more information. * * @since 1.5 */ public void repaint();
JLayeredPane
maintains a HashTable
of the Components
it contains. It does not currently override removeAll
to update the HashTable
, resulting in a possible leak.
JLayeredPane
will now override removeAll
to do the necessary cleanup:
/** * Removes all the components from this container. * * @since 1.5 */ public void removeAll();
Swing classes document the default value of many properties. Custom look and feels may change these values so that it appears that the default isn't valid, this needs to be clarified. To document this, the following was added to JComponent's class level javadoc:
* <code>JComponent</code> and its subclasses document default values * for certain properties. For example, <code>JTable</code> documents the * default row height as 16. Each <code>JComponent</code> subclass * that has a <code>ComponentUI</code> will create the * <code>ComponentUI</code> as part of its constructor. In order * to provide a particular look and feel each * <code>ComponentUI</code> may set properties back on the * <code>JComponent</code> that created it. For example, a custom * look and feel may require <code>JTable</code>s to have a row * height of 24. The documented defaults are the value of a property * BEFORE the <code>ComponentUI</code> has been installed. If you * need a specific value for a particular property you should * explicitly set it.
Since 1.4, the JFileChooser
code has too strong a dependence on the native layer. An attempt
was made to bypass this class for programs that use a customized
"virtual" filesystem, but the algorithm is not 100% reliable. To
toggle this behavior, use the client property
FileChooser.useShellFolder
, for example, to turn off
use of the native set this to false
:
jFileChooser.putClientProperty("FileChooser.useShellFolder", Boolean.FALSE);
It is currently rather difficult to construct some common layouts with SpringLayout. Builders have requested a couple methods to make it easier to create common layouts with SpringLayout, as well as to make it easier to persist SpringLayout.
The following has been added to Spring:
/** * Returns a spring whose <em>minimum</em>, <em>preferred</em>, <em>maximum</em> * and <em>value</em> properties are each multiples of the properties of the * argument spring, <code>s</code>. Minimum and maximum properties are * swapped when <code>factor</code> is negative (in accordance with the * rules of interval arithmetic). * <p> * When factor is, for example, 0.5f the result represents 'the mid-point' * of its input - an operation that is useful for centering components in * a container. * * @param s the spring to scale * @param factor amount to scale by. * @return a spring whose properties are those of the input spring <code>s</code> * multiplied by <code>factor</code> * @throws NullPointerException if <code>s</code> is null * @since 1.5 */ public static Spring scale(Spring s, float factor); /** * Returns a spring whose <em>minimum</em>, <em>preferred</em>, <em>maximum</em> * and <em>value</em> properties are defined by the widths of the <em>minimumSize</em>, * <em>preferredSize</em>, <em>maximumSize</em> and <em>size</em> properties * of the supplied component. The returned spring is a 'wrapper' implementation * whose methods call the appropriate size methods of the supplied component. * The minimum, preferred, maximum and value properties of the returned spring * therefore report the current state of the appropriate properties in the * component and track them as they change. * * @param c Component used for calculating size * @return a spring whose properties are defined by the horizontal component * of the component's size methods. * @throws NullPointerException if <code>c</code> is null * @since 1.5 */ public static Spring width(Component c); /** * Returns a spring whose <em>minimum</em>, <em>preferred</em>, <em>maximum</em> * and <em>value</em> properties are defined by the heights of the <em>minimumSize</em>, * <em>preferredSize</em>, <em>maximumSize</em> and <em>size</em> properties * of the supplied component. The returned spring is a 'wrapper' implementation * whose methods call the appropriate size methods of the supplied component. * The minimum, preferred, maximum and value properties of the returned spring * therefore report the current state of the appropriate properties in the * component and track them as they change. * * @param c Component used for calculating size * @return a spring whose properties are defined by the vertical component * of the component's size methods. * @throws NullPointerException if <code>c</code> is null * @since 1.5 */ public static Spring height(Component c);
And the following has been added to SpringLayout.Constraints:
/** * Creates a <code>Constraints</code> object with * suitable <code>x</code>, <code>y</code>, <code>width</code> and * <code>height</code> springs for component, <code>c</code>. * The <code>x</code> and <code>y</code> springs are constant * springs initialised with the component's location at * the time this method is called. The <code>width</code> and * <code>height</code> springs are special springs, created by * the <code>Spring.width()</code> and <code>Spring.height()</code> * methods, which track the size characteristics of the component * when they change. * * @param c the component whose characteristics will be reflected by this Constraints object * @throws NullPointerException if <code>c</code> is null. * @since 1.5 */ public Constraints(Component c);
Contrary to AWT programming, JFrame/JDialg/JWindow/JApplet/JInternalFrame
do not allow you to add Component
s to it, instead you
must learn about JRootPane
and add children Components
to it. This adds needless confusion to new developers.
Prior to 5.0, attempting to add or remove a
Component
from one of these top level
Component
s would result in an exception be thrown. In
5.0, no exception will be thrown, instead the
Component
will be added or removed from the content
pane. This resulted in several revisions to the javadoc of
JFrame
, JDialog
, JWindow
,
JApplet
and JInternalFrame
. This has been
summarized in RootPaneContainer's
javadoc:
* For conveniance * <code>JFrame</code>, <code>JDialog</code>, <code>JWindow</code>, * <code>JApplet</code> and <code>JInternalFrame</code>, by default, * forward all calls to <code>add</code> and its variants, * <code>remove</code> and <code>setLayout</code> to the * <code>contentPane</code>. This means rather than writing: * <pre> * rootPaneContainer.getContentPane().add(component); * </pre> * you can do: * <pre> * rootPaneContainer.add(component); * </pre> * <p> * The behavior of <code>add</code> and its variants and * <code>setLayout</code> for * <code>JFrame</code>, <code>JDialog</code>, <code>JWindow</code>, * <code>JApplet</code> and <code>JInternalFrame</code> is controlled by * the <code>rootPaneCheckingEnabled</code> property. If this property is * true, the default, then <code>add</code> and its variants and * <code>setLayout</code> are * forwarded to the <code>contentPane</code>, if it is false, then these * methods operate directly on the <code>RootPaneContainer</code>. This * property is only intended for subclasses, and is therefor protected.
The documentation for JFileChooser is not clear on where to tell the file chooser whether files, directories or both are to be selected. This resulted in revising the documentation for the following methods:
/** * Adds a filter to the list of user choosable file filters. * For information on setting the file selection mode, see * {@link #setFileSelectionMode setFileSelectionMode}. * * @param filter the <code>FileFilter</code> to add to the choosable file * filter list * * @beaninfo * preferred: true * bound: true * description: Adds a filter to the list of user choosable file filters. * * @see #getChoosableFileFilters * @see #removeChoosableFileFilter * @see #resetChoosableFileFilters * @see #setFileSelectionMode */ public void addChoosableFileFilter(FileFilter filter); /** * Sets the <code>JFileChooser</code> to allow the user to just * select files, just select * directories, or select both files and directories. The default is * <code>JFilesChooser.FILES_ONLY</code>. * * @param mode the type of files to be displayed: * <ul> * <li>JFileChooser.FILES_ONLY * <li>JFileChooser.DIRECTORIES_ONLY * <li>JFileChooser.FILES_AND_DIRECTORIES * </ul> * * @exception IllegalArgumentException if <code>mode</code> is an * illegal file selection mode * @beaninfo * preferred: true * bound: true * description: Sets the types of files that the JFileChooser can choose. * enum: FILES_ONLY JFileChooser.FILES_ONLY * DIRECTORIES_ONLY JFileChooser.DIRECTORIES_ONLY * FILES_AND_DIRECTORIES JFileChooser.FILES_AND_DIRECTORIES * * * @see #getFileSelectionMode */ public void setFileSelectionMode(int mode);
Invoking JDesktopPane.setDesktopManager does not take affect until the UI is reloaded.
To fix this BasicDesktopPaneUI will not override the following methods:
/** * Installs the <code>PropertyChangeListener</code> returned from * <code>createPropertyChangeListener</code> on the <code>JDesktopPane</code>. * * @since 1.5 * @see #createPropertyChangeListener */ protected void installListeners() /** * Uninstalls the <code>PropertyChangeListener</code> returned from * <code>createPropertyChangeListener</code> from the <code>JDesktopPane</code>. * * @since 1.5 * @see #createPropertyChangeListener */ protected void uninstallListeners() /* * Returns the <code>PropertyChangeListener</code> to install on * the <code>JDesktopPane</code>. * * @since 1.5 * @return The PropertyChangeListener that will be added to track * changes in the desktop pane. */ protected PropertyChangeListener createPropertyChangeListener()
To cut down on the per instance size of various JComponent subclasses the following changes have been made.
To avoid duplicate storage of the preferred, minimum and maximum
size of JComponent
's the following methods have been
promoted to Component
:
/** * Sets the preferred size of this component to a constant * value. Subsequent calls to <code>getPreferredSize</code> will always * return this value. Setting the preferred size to <code>null</code> * restores the default behavior. * * @param preferredSize The new preferred size, or null * @see #getPreferredSize * @see #isPreferredSizeSet * @since 1.5 */ public void setPreferredSize(Dimension preferredSize); /** * Returns true if the preferred size has been set to a * non-<code>null</code> value otherwise returns false. * * @return true if <code>setPreferredSize</code> has been invoked * with a non-null value. * @since 1.5 */ public boolean isPreferredSizeSet(); /** * Sets the minimum size of this component to a constant * value. Subsequent calls to <code>getMinimumSize</code> will always * return this value. Setting the minimum size to <code>null</code> * restores the default behavior. * * @param minimumSize the new minimum size of this component * @see #getMinimumSize * @see #isMinimumSizeSet * @since 1.5 */ public void setMinimumSize(Dimension minimumSize); /** * Returns whether or not <code>setMinimumSize</code> has been * invoked with a non-null value. * * @return true if <code>setMinimumSize</code> has been invoked with a * non-null value. * @since 1.5 */ public boolean isMinimumSizeSet(); /** * Sets the maximum size of this component to a constant * value. Subsequent calls to <code>getMaximumSize</code> will always * return this value. Setting the maximum size to <code>null</code> * restores the default behavior. * * @param maximumSize a <code>Dimension</code> containing the * desired maximum allowable size * @see #getMaximumSize * @see #isMaximumSizeSet * @since 1.5 */ public void setMaximumSize(Dimension maximumSize); /** * Returns true if the maximum size has been set to a non-<code>null</code> * value otherwise returns false. * * @return true if <code>maximumSize</code> is non-<code>null</code>, * false otherwise * @since 1.5 */ public boolean isMaximumSizeSet();
To improve memory needed for autoscrolling
JComponent
will now override the following method:
/** * Processes mouse events occurring on this component by * dispatching them to any registered * <code>MouseListener</code> objects, refer to * {@link java.awt.Component#processMouseEvent(MouseEvent)} * for a complete description of this method. * * @param e the mouse event * @see java.awt.Component#processMouseEvent * @since 1.5 */ protected void processMouseEvent(MouseEvent e);
To reduce the size of AbstractButton
's the
following methods will be overriden:
/** * Adds the specified component to this container at the specified * index, refer to * {@link java.awt.Container#addImpl(Component, Object, int)} * for a complete description of this method. * * @param comp the component to be added * @param constraints an object expressing layout constraints * for this component * @param index the position in the container's list at which to * insert the component, where <code>-1</code> * means append to the end * @exception IllegalArgumentException if <code>index</code> is invalid * @exception IllegalArgumentException if adding the container's parent * to itself * @exception IllegalArgumentException if adding a window to a container * @since 1.5 */ protected void addImpl(Component comp, Object constraints, int index); /** * Sets the layout manager for this container, refer to * {@link java.awt.Container#setLayout(LayoutManager)} * for a complete description of this method. * * @param mgr the specified layout manager * @since 1.5 */ public void setLayout(LayoutManager mgr);
Swing documents the key bindings for various components in the files Key-Index.html, Key-Metal.html, Key-Motif.html and Key-Windows.html. These files are in the directory src/share/classes/javax/swing/doc-files and are referenced by a handful of Swing widgets. These files are extremely dated and never really documented all of Swing's key bindings, they have been removed along with all references to them.
Swing's UIManager class is
used, among other things, to find out the name of the class that
can be used to provide the look and feel for the current system. On
Solaris w/Gnome the call getSystemLookAndFeelClassName
should return the package name for the GTK look and feel.
This resulted in the following changes to
UIManager
:
/** * Returns the name of the <code>LookAndFeel</code> class that implements * the native systems look and feel if there is one, otherwise * the name of the default cross platform <code>LookAndFeel</code> * class. If the system property <code>swing.systemlaf</code> has been * defined, it's value will be returned. * * @return the <code>String</code> of the <code>LookAndFeel</code> * class * * @see #setLookAndFeel * @see #getCrossPlatformLookAndFeelClassName */ public static String getSystemLookAndFeelClassName(); /** * Returns the name of the <code>LookAndFeel</code> class that implements * the default cross platform look and feel -- the Java * Look and Feel (JLF). If the system property * <code>swing.crossplatformlaf</code> has been * defined, it's value will be returned. * * @return a string with the JLF implementation-class * @see #setLookAndFeel * @see #getSystemLookAndFeelClassName */ public static String getCrossPlatformLookAndFeelClassName();
As part of this work we also created the
WindowsClassicLookAndFeel
. This class is useful to
force the windows classic look to be used even if you are running
XP.
As a precursor to providing antialiased text in Swing JComponent will now override the following method:
/** * Gets the <code>FontMetrics</code> for the specified <code>Font</code>. * * @param font the font for which font metrics is to be * obtained * @return the font metrics for <code>font</code> * @throws NullPointerException if <code>font</code> is null * @since 1.5 */ public FontMetrics getFontMetrics(Font font);
A handful of these API changes have introduced potential incompatibilities between 5.0 and previous releases. Very few developers will be affected by these changes. The possible incompatibilities are listed below:
Ocean draws a gradient on buttons. The gradient will only be
drawn if the contentAreaFilled
property is true, or
the background
property is an instance of
UIResource
. If you do not want the gradient, either
set the contentAreaFilled
property to false, or set
the background to a non-UIResource
. In most cases this
is a simple as:
button.setBackground(Color.RED);
If, for some reason, you are picking up a
UIResource
you need to create a new Color
that is not a UIResource
, for example:
button.setBackground(new Color(oldColor));
JTree
and JList
interpret cursor
movement relative to the lead. For example, if the lead is on row
four in a JTree
and you press the up key the selection
changes to row three. Similarly, JTree
and
JList
pass an argument to their renderers indicating
whether the item being rendered has the focus; this is based on
whether the item being rendered is the lead. Prior to 5.0,
JTable
used the anchor for these situations; in 5.0,
JTable
uses the lead. This could affect developers
that were assuming the anchor was the cell that has the focus and
could result in rendering a focus indicator in the wrong
situations.
To render the popup for a JComboBox
Sun's look and
feels use an instance of JScrollPane
. The
JScrollPane
is configured to never have a horizontal
scroll bar. In 5.0 setHorizontalScrollBar(null)
is now
invoked.