Implications of Swing's pluggable look and feel

Thursday Feb 12th 1998 by Ted M. Young
Share:

The idea of a "pluggable look and feel," or PLaF for short, plays a prominent role in the Swing set of widgets (user-interface components), in JavaSoft's Java Foundation Classes (JFC) release in JDK 1.2.

February 12, 1998
Implications of Swing's pluggable look and feel

by Ted M. Young

The idea of a "pluggable look and feel," or PLaF for short, plays a prominent role in the Swing set of widgets (user-interface components), in JavaSoft's Java Foundation Classes (JFC) release in JDK 1.2. A "look and feel" (LaF) refer to components' appearance (grey vs. white, flat vs. three-dimensional, etc.) and their interactions with users (how they react to keypresses, mouseclicks and the features they offer, such as floating toolbars). A PLaF means that you can write your program using a particular look-and-feel, for example the Windows 95 LaF, and then at runtime you can switch to another LaF, such as Motif, or the new "Organic" LaF (developed specifically for use in Java), or even a pen-based LaF for palm computers. This saves developers the trouble of changing user-interface code.

However, this advantage has some ramifications that you need to be aware of. In particular, you can't always assume that a particular LaF offers the features that you want. An example (prompted by a question in the JavaGUI section of developer.com's Discussions area) is found in the dockable toolbar and, in particular, the ability to programatically control whether the toolbar is docked or floating. As of Swing 0.7.1, the JToolBar component (the Swing toolbar) does not offer methods to support the control of a dockable toolbar, even though the Windows LaF and the Java LaF both support dockable toolbars (alas, the dockable feature is somewhat buggy in this release of Swing).

So what to do? The answer is to use the code included with this article, which shows how to access methods in the underlying user interface (i.e., the specific LaF being used). This demo application creates a window with three buttons (ok, four, but the first one is just for show): float, unfloat and exit. When you click on the Float button, the toolbar floats in its own top-level window that you can drag around the screen. When you click on the Unfloat button, the toolbar returns to its home frame. I'll leave the effect of the Exit button to your imagination.

These tasks are accomplished with the

actionPerformed
method (this method gets called when you click on the button):

First, we get a reference to the underlying user-interface object, in this case a

ToolBarUI
object:

ToolBarUI tbUI = m_tb.getUI(); // m_tb is a reference to our JToolBar instance

Then we see if this particular UI object is a

BasicToolBarUI
, because we know that
BasicToolBarUI
s support floating toolbars:
if ( tbUI instanceof BasicToolBarUI ) {

Then, if it is a

BasicToolBarUI
, we can access the
BasicToolBarUI
's methods for controlling the floating aspect of the toolbar. First, we cast the tbUI reference to
BasicToolBarUI
so we can invoke the
setFloatingLocation()
method (we'll float the toolbar at coordinates 50,50 on the screen):
( ( BasicToolBarUI ) tbUI).setFloatingLocation( 50, 50 );

Then we'll actually force the toolbar to float by invoking

setFloating()
, again casting to a
BasicToolBarUI
:
( ( BasicToolBarUI ) tbUI).setFloating( true, null );

And, since there are some painting bugs in Swing, we force some repaints:

m_tb.repaint();
repaint();

To Unfloat, we simply use the same method to invoke

setFloating()
with a false parameter to stop floating.

And that's it! Keep in mind that this fix is specific to

BasicToolBarUI
types. We could check for other types, but any other LaF implementation would be specific to that LaF.

There are other

BasicToolBarUI
-specific methods that we can invoke in the same manner. Take a look at the Swing documentation in the com.java.swing.basic package for more.

Note that JavaSoft may change the JToolBar implementation and "pull" the floating functionality from the underlying UI, thereby forcing all LaFs to support floating toolbars, which would make this example moot. However, there will always be times when you need to access specific features of the underlying LaF user-interface implementation.

See the code mentioned in this article.

Join Ted for more Java talk in the developer.com Discussions area.

Ted M. Young, CTO and co-founder of Advanced Web Technologies Corp., a Java training and mentoring company, has been busy transferring his Java knowledge to developers since 1995 through hands-on training, mentoring, and writing. Besides Java, his specialties include object-oriented design and architecture and user interface design. You can write him at: tyoung@javatrain.com.


/**
 ** ToolBar Demo showing how to float/unfloat a dockable toolbar using the "Basic" ToolBar UI
 **
 ** Note that this code works with the JDK 1.1.x (1.1.5 was actually tested) and Swing 0.7.1.
 **
 ** @Author Ted M. Young <tyoung@javatrain.com> URL: http://www.javatrain.com
 ** @Date January 29, 1997
 **
 ** This code may be freely used and disseminated, no acknowledgements necessary.
 ** No warranties are implied, use at your own risk.
 **
 **/

// import for layout
import java.awt.BorderLayout;

// import for responding to events
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowAdapter;

// the Swing components that we use
import com.sun.java.swing.JFrame;
import com.sun.java.swing.JToolBar;
import com.sun.java.swing.JButton;

// the UIs behind the JToolBar
import com.sun.java.swing.basic.BasicToolBarUI;
import com.sun.java.swing.plaf.ToolBarUI;

public class ToolBarDemo extends JFrame {

   JToolBar m_tb = null;   // our ToolBar

   public ToolBarDemo() {  // constructor

      // set the title for this frame
      super( "Docking and Floating Toolbar Demo" );

      // a button to fill up some space
      JButton btnDontPushMe = new JButton( "Don't Push Me" );
      btnDontPushMe.setEnabled( false );  // we don't need to enable it

      // the 'float me' button
      JButton btnFloat = new JButton( "Float" );
      // add a listener to do something when we click on this button
      btnFloat.addActionListener( new ActionListener() {
         public void actionPerformed( ActionEvent e ) {
            // get the toolbar's user interface
            ToolBarUI tbUI = m_tb.getUI();
            // the BasicToolBarUI supports the idea of floating
            if ( tbUI instanceof BasicToolBarUI ) {
               // set a location other than the very upper-left of the screen
               ( ( BasicToolBarUI ) tbUI).setFloatingLocation( 50, 50 );
               // and float away -- the null is to match the Point parameter which we don't use
               ( ( BasicToolBarUI ) tbUI).setFloating( true, null );
            }
         }
      });

      // same thing as the float button, but this time we turn the floating off
      JButton btnUnfloat = new JButton( "Unfloat" );
      btnUnfloat.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            ToolBarUI tbUI = m_tb.getUI();
            if (tbUI instanceof BasicToolBarUI) {
               ( ( BasicToolBarUI ) tbUI).setFloating(false, null);
            }
         }
      });

      // always nice to provide an exit
      JButton btnExit = new JButton( "Exit" );
      btnExit.addActionListener( new ActionListener() {
         public void actionPerformed( ActionEvent e ) {
            System.exit(0);
         }
      });

      // let's create the toolbar and add the above buttons to it
      m_tb = new JToolBar();

      m_tb.add( btnDontPushMe );
      m_tb.addSeparator();

      m_tb.add( btnFloat );
      m_tb.addSeparator();

      m_tb.add( btnUnfloat );      
      m_tb.addSeparator();

      m_tb.add( btnExit );
      
      // Default layout for the content pane is BorderLayout
      // remember, we need to add to the content pane in a JFrame
      getContentPane().add( m_tb, BorderLayout.NORTH );
   }

   /**
    *  Create the ToolBarDemo frame and display it
    **/
   public static void main( String[] args ) {
   
      JFrame frmTest = new ToolBarDemo();
      frmTest.addWindowListener( new WindowAdapter() {
         public void windowClosing( WindowEvent e ) {
            System.exit( 0 );
         }
       });

       // Set the size of the JFrame and show it
       frmTest.setSize( 400, 200 );
       frmTest.setVisible( true );
      
   }

}


Share:
Home
Mobile Site | Full Site
Copyright 2017 © QuinStreet Inc. All Rights Reserved