Easy to Learn Java: Programming Articles, Examples and Tips

Start with Java in a few days with Java Lessons or Lectures

Home

Code Examples

Java Tools

More Java Tools!

Java Forum

All Java Tips

Books

Submit News
Search the site here...
Search...
 

Swing Chapter 12 (The basics) Menus, Toolbars, and Actions. Easy for reading, Click here!

Custom Search
Swing Chapter 12 (The basics) Menus, Toolbars, and Actions. Easy for reading, Click here!

[ Return to Swing (Book) ]

Page: 1/5 



Next Page (2/5) Next Page

Chapter 12. Menus, Toolbars, and Actions

Subpages: 1. JMenus, Toolbars, and Actions overview 
2.
Basic text editor: part I - menus 
3.
Basic text editor: part II - Toolbars and Actions 
4. Basic text editor: part III - Custom toolbar components 
5. Basic text editor: part IV- Custom menu components 

In this chapter:

  •          Menus, Toolbars, and Actions overview
  •          Basic text editor: part I - Menus
  •          Basic text editor: part II - Toolbars and Actions
  •          Basic text editor: part III - Custom toolbar components
  •          Basic text editor: part IV- Custom menu components

12.1  Menus, toolbars, and actions overview

Drop-down menu bars, context-sensitive popup menus, and draggable toolbars have become commonplace in many modern applications. It is no surprise that Swing offers these features, and in this section we will discuss the classes and interfaces that underly them. The remainder of this chapter is then devoted to the stepwise construction of a basic text editor application to demonstrate each feature discussed here.

12.1.1  The SingleSelectionModel interface

abstract interface javax.swing.SingleSelectionModel

This simple interface describes a model which maintains a single selected element from a given collection. Methods to assign, retrieve, and clear a selected index are declared, as well as methods for attaching and removing ChangeListeners. Implementations are responsible for the storage and manipulation of the collection to be selected from, maintaining an int property representing the selected element, maintaining a boolean property specifying whether or not an element is selected, and are expected to fire ChangeEvents whenever the selected index changes.

12.1.2 DefaultSingleSelectionModel

class javax.swing.DefaultSelectionModel

This is the default implementation of SingleSelectionModel used by JMenuBar and JMenuItem. The selectedIndex property represents the selected index at any given time and is -1 when nothing is selected. As expected we can add and remove ChangeListeners, and the protected fireStateChanged() method is responsible for dispatching ChangeEvents whenever the selectedIndex property changes.

12.1.3  JMenuBar

class javax.swing.JMenuBar

JMenuBar is a container for JMenus layed out horizontally in a row, typically residing at the top of a frame or applet. We use the add(JMenu menu) method to add a new JMenu to a JMenuBar. We use the setJMenuBar() method in JFrame, JDialog, JApplet, JRootPane, and JInternalFrame to set the menu bar for these containers (recall that each of these containers implements RootPaneContainer, which enforces the definition of setJMenuBar()--see chapter 3). JMenuBar uses a DefaultSingleSelectionModel to enforce the selection of only one child at any given time.

A JMenuBar is a JComponent subclass and, as such, can be placed anywhere in a container just as any other Swing component (this functionality is not available with AWT menu bars).

Warning: JMenuBar defines the method setHelpMenu(JMenu menu) which is intened to mark a single menu contained in a JMenuBar as the designated 'help' menu. The JMenuBar UI delegate may be responsible for positioning and somehow treating this menu differently than others. Hoewever, this is not implemented as of Java 2 FCS, and generates an exception if used.

Note: One lacking feature in the current JMenuBar implementation, or its UI delegate, is the ability to easily control the spacing between its JMenu children. As of Java 2 FCS, the easiest way to control this is by overriding JMenuBar and manually taking control of its layout. By default JMenubar uses an x-oriented BoxLayout.

JMenuBar provides several methods to retrieve its child components, set/get the currently selected item, register/unregister with the current KeyBoardManager (see chapter 2, section 2.13), and the isManagingFocus() method which simply returns true to indicate that JMenuBar handles focus management internally. Public methods processKeyEvent() and processMouseEvent() are implemented only to satisfy the MenuElement interface (see below) requirements, and do nothing by default.

12.1.4  JMenuItem

class javax.swing.JMenuItem

This class extends AbstractButton (see chapter 4, section 4.1) and represents a single menu item. We can assign icons and keyboard mnemonics just as we can with buttons. A mnemonic is represented graphically by underlining the first instance of the corresponding character, just as it is in buttons. Icon and text placement can be dealt with identically to how we deal with this functionality in buttons.

We can also attach keyboard accelerators to a JMenuItem.(i.e. we can register keyboard actions with a JMenuItem -- see chapter 2 section 2.13). Every JComponent decendent inherits similar functionality. When assigned to a JMenuItem, the accelerator will appear as small text to the right of the menu item text. An accelerator is a key or combination of keys that can be used to activate a menu item. Contrary to a mnemonic, an accelerator will invoke a menu item even when the popup containing it is not visible. The only necessary condition for accelerator activation is that the window containing the target menu item is currently active. To add an accelerator corresponding to CTRL+A we can do the following:

  myJMenuItem.setAccelerator(KeyStroke.getKeyStroke(

    KeyEvent.VK_A, KeyEvent.CTRL_MASK, false);

Note: JMenuItem is the only Swing component that graphically displays an assigned keyboard accelerator.

We normally attach an ActionListener to a menu item. As any button, whenever the menu item is clicked the ActionListener is notified. Alternatively we can use Actions (discussed below and briefly in 2.13) which provide a convenient means of creating a menu item as well as definining the corresponding action handling code. A single Action instance can be used to create an arbitrary number of JMenuItems and JButtons with identical action handling code. We will see how this is done soon enough. It suffices to say here that when an Action is disabled, all JMenuItems associated with that Action are disabled and, as buttons always do in the disabled state, appear grayed out.

As any AbstractButton decendent, JMenuItem fires ActionEvents and ChangeEvents and allows attachment of ActionListeners and ChangeListeners accordingly. JMenuItem will also fire MenuDragMouseEvents (see below) when the mouse enters, exits, is dragged, or a mouse button is released inside its bounds, and MenuKeyEvents when a key is pressed, typed, or released. Both of these Swing-specific events will only be fired when the popup containing the corresponding menu item is visible. As expected, we can add MenuDragMouseListeners and MenuKeyEventListeners for notification of these events. Several public processXXEvent() methods are also provided to receive and respond to events dispatched to a JMenuItem, some of which are forewarded from the current MenuSelectionManager (see below).

12.1.5  JMenu

class javax.swing.JMenu

This class extends JMenuItem and is usually added to a JMenuBar or to another JMenu. In the former case it will act as a menu item which pops up a JPopupMenu containing child menu items. If a JMenu is added to another JMenu it will appear in that menu's corresponding popup as a menu item with an arrow on its right side. When that menu item is activated by mouse movement or keyboard selection a popup will appear displaying its corresponding child menu items. Each JMenu maintains a topLevelMenu property which is false for sub-menus and true otherwise.

JMenu uses a DefaultButtonModel to manage its state, and it holds a private instance of JPopupMenu (see below) used to display its associated menu items when it is activated with the mouse or a keyboard mnemonic.

Note: Unlike its JMenuItem parent, JMenu specifically overrides setAccelerator() with an empty implementation to disallow keyboard accelerators. This is because it assumes that we will only want to activate a menu (i.e. display its popup) when it is already visible; and for this we can use a mnemonic.

We can display/hide the associated popup programmatically by setting the popupMenuVisible property, and we can access the popup using getPopupMenu(). We can set the coordinate location where the popup is displayed with setMenuLocation(). We can assign a specific delay time in milliseconds using setDelay() to specify how long a JMenu should wait before displaying its popup when activated.

We use the overloaded add() method to add JMenuItems, Components, Actions (see below) or Strings to a JMenu. (Adding a String simply creates a JMenuItem child with the given text.) Similarly we can use several variations of overloaded insert() and remove() methods to insert and remove existing children. JMenu also directly supports creation and insertion of separator components in its popup, using addSeparator(), which provides a convenient means of visually organizing child components into groups.

The protected createActionChangeListener() method is used when an Action is added to a JMenu to create a PropertyChangeListener for internal use in responding to bound property changes that occur in that Action (see below). The createWinListener() method is used to create an instance of the protected inner class JMenu.WinListener which is used to deselect a menu when its corresponding popup closes. We are rarely concerned with these methods, and only subclasses desiring a more complete customization will override them.

Along with event dispatching/handling inherited from JMenuItem, JMenu adds functionality for firing and capturing MenuEvents (see below) used to notify attached MenuListeners when its current selection changes.

UI Guideline : Flat and wide design

Recent research in usability has shown that menus with too many levels of hierachy don't work well. Features get buried too many layers deep. Some operating systems restrict menus to 3 levels i.e. the main menu bar, a pull down menu and a single walking pop-up menu.

A maximum 3 Levels would be appear to be a good rule of thumb. Don't be tempted to use popup menus to create a complex series of hierarchical choices. Keep menus flatter.

For each menu, another good rule of thumb is to provide 7 +/- 2 options. However, if you have too many choices, it is better to break this rule and go to 10 or more than to introduce additional hierarchy.

12.1.6  JPopupMenu

class javax.swing.JPopupMenu

This class represents a small window which pops up and contains a collection of components layed out in a single column by default using, suprisingly, a GridBagLayout (note that there is nothing stopping us from changing JPopupMenu's layout manager). JPopupMenu uses a DefaultSingleSelectionModel to enforce the selection of only one child at any given time.

JMenu simply delegates all its add(), remove(), insert(), addSeparator(), etc., calls to its internal JPopupMenu. As expected, JPopupMenu provides similar methods. The addSeparator() method inserts an instance of the inner class JPopupMenu.Separator (a subclass of JSeparator -- discussed below). The show() method displays a JPopupMenu at a given position within the corrdinate system of a given component. This component is referred to as the invoker component, and JPopupMenu can be assigned an invoker by setting its invoker property. JComponent's setVisible() method is overriden to display a JPopupMenu with respect to its current invoker, and we can change the location it will appear using setLocation(). We can also control a JPopupMenu's size with the overloaded setPopupSize() methods, and we can use the pack() method (similar to the java.awt.Window method of the same name) to request that a popup change size to the minimum required for correct display of its child components.

Note: JComboBox's UI delegate uses a JPopupMenu subclass to display its popup list.

When the need arises to display our own JPopupMenu, it is customary, but certainly not necessary, to do so in response to a platform-dependent mouse gesture (e.g. a right-click on Windows platforms). Thus, the java.awt.event.MouseEvent class provides a simple method we can use in a platform-independent manner to check whether a platform-dependent popup gesture has occurred. This method, isPopupTrigger(), will return true if the MouseEvent it is called on represents the current operating system's popup trigger gesture.

JPopupMenu has the unique ability to act as either a heavyweight or lighweight component. It is smart enough to detect when it will be displayed completely within a Swing container or not and adjust itself accordingly. However, there may be cases in which the default behavior may not be acceptable. Recall from chapter 2 that we must set JPopupMenu's lightWeightPopupEnabled property to false to force it to be heavyweight and allow overlapping of other heavyweight components that might reside in the same container.  Setting this property to true will force a JPopupMenu to remain lightweight. The static setDefaultLightWeightPopupEnabled() method serves the same purpose, but affects all JPopupMenu's created from that point on (in the current implementation all popups existing before this method is called will retain their previous lightweight/heavyweight settings).

Bug Altert! Due to an AWT bug, all popups are forced into lightweight mode when displayed in modal dialogs (regardless of the state of the lightWeightPopupEnabled property).

The protected createActionChangeListener() method is used when an Action  (see below) is added to a JPopupMenu to create a PropertyChangeListener for internal use in responding to bound property changes that occur in that Action.

A JPopupMenu fires PopupMenuEvents (discussed below) whenever it is made visible, hidden, and cancelled. As expected we can attatch PopupMenuListeners to capture these events.

12.1.7  JSeparator

class javax.swing.JSeparator

This class represents a simple separator component with a UI delegate responsible for displaying a horizontal or vertical line. We can specify which orientation a JSeparator should use by changing its orientation property. This class is most often used in menus and toolbars, however, it is a standard Swing component and there is nothing stopping us from using JSeparators anywhere we like.

We normally do not use JSeparator explicitly. Rather, we use the  addSeparator() method of JMenu, JPopupMenu, and JToolBar. JMenu delegates this call to its JPopupMenu which, as we know, uses an instance of its own custom JSeparator subclass which is rendered as a horizontal line. JToolBar also uses its own custom JSeparator sub-class which has no graphical representation, and appears as just an empty region. Unlike menu separators, however, JToolBar's separator allows explicit instantiation and provides a method for assigning a new size in the form of a Dimension.

UI Guideline : Use of a separator

Use a separator to group related menu choices and separate them from others. This gives better visual communication and better usability by providing a space between the target areas for groups of choices. This reduces the chance of an error when making a selection with the mouse.

12.1.8  JCheckBoxMenuItem

class javax.swing.JCheckBoxMenuItem

This class extends JMenuItem and can be selected, deselected, and rendered identical to JCheckBox (see chapter 4). We use the isSelected()/setSelected() or getState()/setState() methods to determine/set the selection state respectively. ActionListeners and ChangeListeners can be attached to a JCheckBoxMenuItem for notification about changes in its state (see JMenuItem discussion for inherited functionality). We often use JCheckBoxMenuItems in ButtonGroups to enforce the selection of only one item in a group at any given time.

12.1.9  JRadioButtonMenuItem

class javax.swing.JRadioButtonMenuItem

This class extends JMenuItem and can be selected, deselected, and rendered identical to JRadioButton (see chapter 4). We use the isSelected()/setSelected() or getState()/setState() methods to determine/set the selection state respectively. ActionListeners and ChangeListeners can be attached to a JRadioButtonMenuItem for notification about changes in its state (see JMenuItem discussion for inherited functionality). We often use JRadioButtonMenuItems in ButtonGroups to enforce the selection of only one item in a group at any given time.

UI Guideline : Widget overloading

As a general rule in UI Design, it is not desirable to overload components and use them for two purposes. By adding Checkboxes or Radio Buttons to a menu, you are changing the purpose of a menu from one of navigation to one of selection. This is an important point to understand.

Making this change is an acceptable design technique when it will speed operation and enhance usability by removing the need for a cumbersome dialog or option pane. However, it is important to assess that it does not otherwise adversely affect usability.

Groups of Radio Button or Checkbox menu items are probably best isolated by using a JSeparator.

12.1.10            The MenuElement interface

abstract interface javax.swing.MenuElement

This interface must be implemented by all components that wish to act as menu items. By implementing the methods of this interface any components can act as a menu item, making it quite easy to build our own.

The getSubElements() method returns an array of MenuElements containing the given item's sub-elements. The processKeyEvent() and processMouseEvent() methods are called to process keyboard and mouse events respectively when the implementing component has the focus. Unlike methods with the same name in the java.awt.Component class, these two methods receive three parameters: the KeyEvent or MouseEvent, respectively, which should be processed, an array of MenuElements which forms the menu path to the implementing component, and the current MenuSelectionManager (see below). The menuSelectionChanged() method is called by the MenuSelectionManager when the implementing component is added or removed from its current selection state. The getComponent() method returns a reference to a component that is responsible for the rendering of the implementing component.

Note: The getComponent() method is interesting, as it allows classes that are not Components themselves to implement the MenuElement interface and act as menu elements when necessary. Such a class must provide a Component used for display in a menu, and this Component would be returned by getComponent(). This design has curious implications, allowing us to design robust JavaBeans that encapsulate an optional GUI representation. We can imagine a complex spell-checker or dictionary class implementing the MenuElement interface and providing a custom component for display in a menu (a powerful and highly object-oriented bean indeed).

JMenuItem, JMenuBar, JPopupMenu, and JMenu all implement this interface. Note that each of their getComponent() methods simply return a this reference. Also note that by extending any of these implementing classes, we inherit MenuElement functionality and are therefore not required to implement it. (We won't explicitly use this interface in any examples, as the custom component we will build at the end of this chapter is an extension of JMenu.)

12.1.11            MenuSelectionManager

class javax.swing.MenuSelectionManager

MenuSelectionManager is a service class responsible for managing menu selection throughout a single Java session. (Note that unlike most other service classes in Swing, MenuSelectionManager does not register its shared instance with AppContext--see chapter 2.) When MenuElement implementations receive MouseEvents or KeyEvents, these events should not be processed directly. Rather, they should be handed off to the MenuSelectionManager so that it may forward them to sub-components automatically. For instance, whenever a JMenuItem is activated by keyboard or mouse, or whenever a JMenuItem selection occurs, the menu item UI delegate is responsible for forwarding the corresponding event to the MenuSelectionManager if necessary. The following code shows how BasicMenuItemUI deals with mouse releases:

    public void mouseReleased(MouseEvent e) {

      MenuSelectionManager manager =

        MenuSelectionManager.defaultManager();

      Point p = e.getPoint();

      if(p.x >= 0 && p.x < menuItem.getWidth() &&

       p.y >= 0 && p.y < menuItem.getHeight()) {

        manager.clearSelectedPath();

        menuItem.doClick(0);

      }

      else {

        manager.processMouseEvent(e);

      }

    }

The static defaultManager() method returns the MenuSelectionManager shared instance, and the clearSelectedPath() method tells the currently active menu hierarchy to close and unselect all menu components. In the code shown above, clearSelectedPath() will only be called if the mouse release occurs within the corresponding JMenuItem (in which case there is no need for the event to propogate any further). If this is not the case, the event is sent to MenuSelectionManager's processMouseEvent() method which forwards it to other sub-components. JMenuItem doesn't have any sub-components by default so not much interesting happens in this case. However, in the case of JMenu, which considers its popup menu a sub-component, sending a mouse released event to the MenuSelectionManager is expected no matter what (from BasicMenuUI):

    public void mouseReleased(MouseEvent e) {

      MenuSelectionManager manager =

        MenuSelectionManager.defaultManager();

      manager.processMouseEvent(e);

      if (!e.isConsumed())

        manager.clearSelectedPath();            

    }

MenuSelectionManager will fire ChangeEvents whenever its setSelectedPath() method is called (i.e. each time a menu selection changes). As expected, we can attach ChangeListeners to listen for these events.

12.1.12            The MenuDragMouseListener interface

abstract interface javax.swing.event.MenuDragMouseListener

This listener receives notification when the mouse cursor enters, exits, is released, or is moved over a menu item.

12.1.13            MenuDragMouseEvent

class javax.swing.event.MenuDragMouseEvent

This event class is used to deliver information to MenuDragMouseListeners. It encapsulates the component source, event id, time of the event, bitwise or-masked int specifying which mouse button and/or keys (CTRL, SHIFT, ALT, or META) were pressed at the time of the event, x and y mouse coordinates, number of clicks immediately preceding the event, whether or not the event represents the platform-dependent popup trigger, an array of MenuElements leading to the source of the event, and the current MenuSelectionManager. This event inherits all MouseEvent functionality (see API docs) and adds two methods for retrieving the array of MenuElements and the MenuSelectionManager.

12.1.14            The MenuKeyListener interface

abstract interface javax.swing.event.MenuKeyListener

This listener is notified when a menu item receives a key event corresponding to a key press, release, or type. These events don't necessarily correspond to mnemonics or accelerators, and are received whenever a menu item is simply visible on the screen.

12.1.15            MenuKeyEvent

class javax.swing.event.MenuKeyEvent

This event class is used to deliver information to MenuKeyListeners. It encapsulates the component source, event id, time of the event, bitwise or-masked int specifying which mouse button and/or keys (CTRL, SHIFT, or ALT) were pressed at the time of the event, an int and char identifying the source key that caused the event, an array of MenuElements leading to the source of the event, and the current MenuSelectionManager. This event inherits all KeyEvent functionality (see API docs) and adds two methods for retrieving the array of MenuElements and the MenuSelectionManager.

12.1.16            The MenuListener interface

abstract interface javax.swing.event.MenuListener

This listener receives notification when a menu is selected, deselected, or cancelled. Three methods must be implemented by MenuListeners, and each takes a MouseEvent parameter: menuCanceled(), menuDeselected(), and menuSelected().

12.1.17            MenuEvent

class javax.swing.event.MenuEvent

This event class is used to deliver information to MenuListeners. It simply encapsulates a reference to its source Object.

12.1.18            The PopupMenuListener interface

abstract interface javax.swing.event.PopupMenuListener

This listener receives notification when a JPopupMenu is about to become visible, hidden, or when it is cancelled. Canceling a JPopupMenu also causes it to be hidden, so two PopupMenuEvents are fired in this case. A cancel occurs when the invoker component is resized or the window containing the invoker changes size or location. Three methods must be implemented by PopupMenuListeners, and each takes a PopupMenuEvent parameter: popupMenuCanceled(), popupMenuWillBecomeVisible(), and popupMenuWillBecomeInvisible().

12.1.19            PopupMenuEvent

class javax.swing.event.PopupMenuEvent

This event class is used to deliver information to PopupMenuListeners. It simply encapsulates a reference to its source Object.

12.1.20            JToolBar

class javax.swing.JToolBar

This class represents the Swing implementation of a toolbar. Toolbars are often placed directly below menu bars at the top of a frame or applet, and act as a container for any component (buttons and combo boxes are most common). The most convenient way to add buttons to a JToolBar is to use Actions (discussed below).

Note: Components often need their alignment setting tweaked to provide uniform positioning within JToolBar. This can be accomplished through use of the setAlignmentY() and setAlignmentX() methods. We will see that this is necessary in the final example of this chapter.

JToolBar also allows convenient addition of an inner JSeparator sub-class, JToolBar.Separator, to provide an empty space for visually grouping components. These separators can be added with either of the overloaded addSeparator() methods, one of which takes a Dimension parameter specifying the size of the separator.

Two orientations are supported, VERTICAL and HORIZONTAL, and managed by JToolBar's orientation property. It uses a BoxLayout layout manager which is dynamically changed between Y_AXIS and X_AXIS when the orientation property changes.

JToolBar can be dragged in and out of its parent container if its floatable property is set to true. When dragged out of its parent, a JToolBar appears as a floating window and its border changes color depending on whether it can re-dock in its parent at a given location. If a JToolBar is dragged outside of its parent and released, it will be placed in its own JFrame which is fully maximizable, minimizable, and closable. When this frame is closed JToolBar will jump back into its most recent dock position in its original parent, and the floating JFrame will disappear. It is recommended that JToolBar is placed in one of the four sides of a container using a BorderLayout, leaving the other sides unused. This allows the JToolBar to be docked in any of that container's side regions.

The protected createActionChangeListener() method is used when an Action  (see below) is added to a JToolBar to create a PropertyChangeListener for internal use in responding to bound property changes that occur in that Action.

UI Guideline : 3 Uses for a Toolbar

Toolbars have become ubiquitious in modern software. However, they are often overused or misused and fail to achieve their objective of increased usability. There are three key uses which have subtle differences and implications.

Tool Selection or Mode Selection

Perhaps the most effective use of a toolbar is, as the name suggests, for the selection of a tool or operational mode. This is most common in drawing or image manipulation packages. The user selects the toolbar button to change the mode from "paintbrush" to "filler" to "draw box" to "cut" etc.. This is a highly effective use of toolbar, as the small icons are usually sufficient to render a suitable tool image. Many images for this purpose have been adopted as a defacto standard. If you are developing such a tool selection toolbar, it would be advisable to stick closely to icons which have been used by similar existing products.

Functional Selection

The earliest use of toolbar was to replace the selection of a specific function from the menu. This led to them being called "speedbars" or "menubars". The idea was that the small icon button was faster and easier to acquire than the menu selection and that usability was enhanced as a result. This worked well for many common functions in file oriented applications, such as "open file", "new file", "save", "cut", "copy" and "paste". In fact, most of us would recognise the small icons for all of these functions. However, with other more application specific functions, it has been much harder for icon designers to come up with appropriate designs. This often leads to applications which have a confusing and intimidating array of icons across the top of the screen. This can detract from usability. As a general rule of thumb, stick to common cross application functions when overloading menu selections with toolbar buttons. If you do need to break the rule then consider selecting annotated buttons for the toolbar.

Navigational Selection

The 3rd use for toolbars has been for navigational selection. This often means replacing or overloading menu options from a "Window", "Go" or "Form" menu. These menu options are used to select a specific screen to come to the front. The toolbar buttons replace or overload the menu option and allow the navigational selection to be made supposedly by faster means. However, again this suffers from the problem of appropriate icon design. It is usually too difficult to devise a suitable set of icons which have clear and unambiguous meaning. Therefore, as a rule of thumb, consider the use of annotated buttons on the toolbar.

12.1.21            Custom JToolBar separators

Unfortunately Swing does not include a toolbar-specific separator component that will display a vertical or horizontal line depending on current toolbar orientation. The following psuedo-code shows how we can build such a component under the assumption that it will always have a JToolBar as direct parent:

  public class MyToolBarSeparator extends JComponent

  {

    public void paintComponent(Graphics g) {

      super.paintComponent(g);

      if (getParent() instanceof JToolBar) {

        if (((JToolBar) getParent()).getOrientation()

         == JToolBar.HORIZONTAL) {

          // paint a vertical line

        }

        else {

          // paint a horizontal line

        }

      }

    }

    public Dimension getPreferredSize() {

      if (getParent() instanceof JToolBar) {

        if (((JToolBar) getParent()).getOrientation()

         == JToolBar.HORIZONTAL) {

          // return size of vertical bar

        }

        else {

          // return size of horizontal bar

        }

      }

    }

  }

UI Guideline : Use of a separator

The failure to include a separator for toolbars really was an oversight by the Swing designers. Again, use the separator to group related functions or tools. For example, if the function all belong on the same menu then group them together, or if the tools (or modes) are related such as "cut", "copy", "paste" then group them together and separate them from others with a separator.

Visual grouping like this improves visual separation by introducing a visual layer. The viewer can first acquire a group of buttons and then a specific button. They will also learn with directional memory the approximate position of each group. By separating them you will improve the usability by helping them to acquire the target better when using the mouse.

12.1.22            Changing JToolBar's floating frame behavior

The behavior of JToolBar's floating JFrame is certainly useful, but it is arguable whether the maximization and resizability should be allowed. Though we cannot control whether or not a JFrame can be maximized, we can control whether or not it can be resized. To enforce non-resizability in JToolBar's floating JFrame (and set its dispayed title while we're at it) we need to override its UI delegate and customize the createFloatingFrame() method as follows:

  public class MyToolBarUI

   extends javax.swing.plaf.metal.MetalToolBarUI {

    protected JFrame createFloatingFrame(JToolBar toolbar) {

      JFrame frame = new JFrame(toolbar.getName());

      frame.setTitle("My toolbar");

      frame.setResizable(false);

      WindowListener wl = createFrameListener();

      frame.addWindowListener(wl);

      return frame;

    }

  }

To assign MyToolBarUI as a JToolBar's UI delegate we can do the following:

  mytoolbar.setUI(new MyToolBarUI());

To force use of this delegate on a global basis we can do the following before any JToolBars are instantiated:

  UIManager.getDefaults().put(

    "ToolBarUI","com.mycompany.MyToolBarUI");

Note that we may also have to add an associated Class instance to the UIDefaults table for this to work (see chapter 21).

UI Guideline : Use of a Floating Frame

It is probably best to restrict the use of a floating toolbar frame to toolbars being used for tool or mode selection (see guideline in 12.1.20).

12.1.23            The Action interface

abstract interface javax.swing.Action

This interface describes a helper object which extends ActionListener and which supports a set of bound properties. We use appropriate add() methods in the JMenu, JPopupMenu, and JToolBar classes to add an Action which will use information from the given instance to create and return a component that is appropriate for that container (a JMenuItem in the case of the first two, a JButton in the case of the latter). The same Action instance can be used to create an arbitrary number of menu items or toolbar buttons.

Because Action extends ActionListener, the actionPerformed() method is inherited and can be used to encapsulte appropriate ActionEvent handling code. When a menu item or toolbar button is created using an Action, the resulting component is registered as a PropertyChangeListener with the Action, and the Action is registered as an ActionListener with the component. Thus, whenever a change occurs to one of that Action's bound properties, all components with registered PropertyChangeListeners will receive notification. This provides a convenient means for allowing identical functionality in menus, toolbars, and popup menus with minimum code repetition and object creation.

The putValue() and getValue() methods are intended to work with a Hashtable-like structure to maintain an Action's bound properties. Whenever the value of a property changes, we are expected to fire PropertyChangeEvents to all registered listeners. As expected, methods to add and remove PropertyChangeListeners are provided.

The Action interface defines five static property keys intended for use by JMenuItems and JButtons created with an Action instance:

String DEFAULT: [not used]

String LONG_DESCRIPTION: Used for a lengthy description of an Action.

String NAME: Used as the text in associated and displayed in JMenuItems and JButtons.

String SHORT_DESCRIPTION: Used for the tooltip text of associated JMenuItems and JButtons.

String SMALL_ICON: Used as the icon in associated JMenuItems and JButtons.

12.1.24            AbstractAction

class javax.swing.AbstractAction

This class is an abstract implementation of the Action interface. Along with the properties inherited from Action, AbstractAction defines the enabled property which provides a means of enabling/disabling all associated components registered as PropertyChangeListeners. A SwingPropertyChangeSupport instance is used to manage the firing of PropertyChangeEvents to all registered PropertyChangeListeners (see chapter 2 for more about SwingPropertyChangeSupport).



[ Return to Swing (Book) ]


Top 10 read Java Articles
 Get free "1000 Java Tips eBook"

 Java Calendar and Date: good to know facts and code examples

 Array vs ArrayList vs LinkedList vs Vector: an excellent overview and examples

 How can I convert any Java Object into byte array? And byte array to file object

 The Java Lesson 1: What is Java?

 How do I compare two dates and times, date between dates, time between times and

 Maven vs Ant or Ant vs Maven?

 How to open, read, write, close file(s) in Java? Examples on move, rename and de

 Java Array

 Java: JLabel font and color


[ More in News Section ]
Java Lessons

The Java Lesson 1:
What is Java?
The Java Lesson 2:
Anatomy of a simple Java program
The Java Lesson 3:
Identifiers and primitive data types
The Java Lesson 4:
Variables, constants, and literals
The Java Lesson 5:
Arithmetic operations, conversions, and casts
The Java Lesson 6:
Boolean expressions and operations
The Java Lesson 7:
Bitwise operations
The Java Lesson 8:
Flow control with if and else
The Java Lesson 9:
switch statements
The Java Lesson 10:
for, while, and do-while statements
The Java Lesson 11:
Using break and continue
The Java Lesson 12:
Class methods and how they are called
The Java Lesson 13:
Using the Math class
The Java Lesson 14:
Creating and calling custom class methods
The Java Lesson 15:
Overloading class methods
The Java Lesson 16:
An introduction to objects and object references
The Java Lesson 17:
The String class
The Java Lesson 18:
The StringBuffer class
The Java Lesson 19:
Initializing and processing arrays of primitives
The Java Lesson 20:
Initializing and processing arrays of objects
The Java Lesson 23:
Inheritance and overriding inherited methods
The Java Lesson 24:
abstract classes and polymorphism
The Java Lesson 25:
Interfaces, instanceof, and object conversion and casting
The Java Lesson 26:
Introduction to graphical programming and the java.awt packa
The Java Lesson 27:
The Component class
The Java Lesson 28:
Containers and simple layout managers
The Java Lesson 29:
The Color and Font classes
The Java Lesson 30:
Drawing geometric shapes
The Java Lesson 31:
Choice, List, and Checkbox controls
The Java Lesson 32:
Using the Scrollbar graphical control
The Java Lesson 33:
Menus and submenus
The Java Lesson 34:
An introduction to applets and the Applet class
The Java Lesson 35:
Essential HTML to launch an applet and pass it parameters
The Java Lesson 36:
Mouse event processing
Java Lesson 37:
Menus and submenus
Java Lesson 38:
The WindowListener interface and the WindowAdapter class
Java Lesson 39:
An introduction to GridBagLayout
Java Lesson 40:
An introduction to the Java Collections API
Java Lesson 41:
Exception handling with try, catch, and finally blocks
Java Lesson 42:
Claiming and throwing exceptions
Java Lesson 43:
Multithreading, the Thread class, and the Runnable interface
Java Lesson 44:
An introduction to I/O and the File and FileDialog classes
Java Lesson 45:
Low-level and high-level stream classes
Java Lesson 46:
Using the RandomAccessFile class
Java Lessons by
Joh Huhtala: Update

Latest articles
 Java Profiler JProbe to Resolve Performance Problems Faster

 SSL with GlassFish v2, page 5

 SSL with GlassFish v2, page 4

 SSL with GlassFish v2, page 3

 SSL with GlassFish v2, page 2

 The Java Lesson 2: Anatomy of a simple Java program, page 2

 New site about Java for robots and robotics: both software and hardware.

 Exceptions -III: What's an exception and why do I care?

 Exceptions -II: What's an exception and why do I care?

 Exceptions: What's an exception and why do I care?

 Double your Java code quality in 10 minutes, here is receipt

 Murach's Java Servlets and JSP

 How to get ascii code from a char in Java?

 Can we just try without catch? Yes!

 Make Tomcat page load faster

 Make your Tomcat More secure - limit network address for certain IP addresses

 New Java book online starts now here...

 Implementing RESTful Web Services in Java

 Firefox trimming from 1 GB to 40 Mb with many tabs opened

 SSL with GlassFish v2

 My request to replublish Tech Tips

 Search JavaFAQ.nu site here

 New Advanced Installer for Java 6.0 brings XML updates and imports 3rd party MSI

 EJB programming restrictions

 Maven vs Ant or Ant vs Maven?

 Why Java does not use default value which it should?

 How to unsign signed bytes in Java - your guide is here

 The Java Lesson 3: Identifiers and primitive data types. Page 2

 The Java Lesson 7: Bitwise operations with good examples, click here! Page 4

 The Java Lesson 7: Bitwise operations with good examples, click here! Page 3


[ More in News Section ]


Home Code Examples Java Forum All Java Tips Books Submit News, Code... Search... Offshore Software Tech Doodling

RSS feed Java FAQ RSS feed Java FAQ News     

    RSS feed Java Forums RSS feed Java Forums

All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest 1999-2006 by Java FAQs Daily Tips.

Interactive software released under GNU GPL, Code Credits, Privacy Policy