HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

A tip window (also known as a tool tip window) is a small popup window that displays a single line of descriptive text. Tip windows are usually displayed over toolbar buttons to provide textual help about a toolbar button's functionality. The tip window control is available for Swing components via the JComponent class's setToolTipText() method; unfortunately, the AWT doesn't have an equivalent control at its disposal. This article details the classes that constitute my implementation of an AWT tip window control.

Implementation
The tip window control is made up of two classes, TipWindow and TipWindowMouseAdapter, located in TipWindow.java.

The TipWindow class (see Listing 1), which extends the java.awt.Window class, contains a single constructor and overrides the java.awt.Container paint() method. The constructor requires four parameters: a java.awt.Frame reference, a java.lang.String reference and two integer values. The constructor first calls the superclass's constructor, passing it the java.awt.Frame reference, which is required when constructing a Window object. Next, the java.lang.String reference is saved to a string instance variable that represents the tip window's help text.

The tip window's background color is set to the ubiquitous yellow found on all tip window controls. A font is chosen and set for the tip window, and a java.awt.FontMetrics object is retrieved on the font currently set. The FontMetrics object is used (1) to calculate a y coordinate for the tip window's help text via the FontMetrics getAscent() method, and (2) to size the tip window using the values returned from the FontMetrics stringWidth() and getHeight() methods. The constant integer variable slack is added to the tip window's width and height to provide a buffer between the help text and the edges of the tip window. The tip window's location is set from the passed integer parameters, which represent an x and y coordinate, and the tip window is finally made visible via the java.awt.Component setVisible() method. Since the Window class doesn't contain any window decorations (e.g., border, title), the overridden paint() method draws a black border around the tip window via the java.awt.Graphics drawRect() method and draws the help text via the java.awt.Graphics drawString() method.

The TipWindowMouseAdapter class (see Listing 2) extends the java.awt.event.MouseAdapter class and contains a constructor and two overridden methods: mouseEntered() and mouseExited(). An adapter class is a convenience class that implements a specific event listener interface (e.g., MouseListener, WindowListener). The adapter class makes it easier to listen for specific events without having to implement all the event listener interface methods since they're already implemented in the adapter class. The TipWindowMouseAdapter constructor requires two parameters: a java.awt.Frame reference and a java.lang.String reference. The Frame reference is the same one that's passed to the TipWindow constructor and represents the tip window's container. The string reference is the name of a properties file (minus the .properties extension), which is a simple text file that contains key-value pairs.

The key identifies the name of a GUI control and the value consists of the control's help text that's displayed in the tip window (more on this later). The properties file is opened and its contents placed in a hashtable for later retrieval via the java.util.ResourceBundle getBundle() method. Resource bundles, backed by properties files, are used primarily to internationalize a Java program. To learn more about resource bundles and internationalizing your Java program, look at the Internationalization section of Sun's Java Tutorial located at http://java.sun.com/docs/books/tutorial/i18n/index.html.

The mouseEntered() method first retrieves the component on which the mouse event occurred and the component's screen location. The tip window is created by instantiating a TipWindow constructor only if the ResourceBundle variable isn't null. The TipWindow constructor is passed the java.awt.Frame reference, the component's help text (retrieved via the java.util.ResourceBundle getString() method using the component's name as the key) and the component's x and y screen coordinates that are added to the mouse's x and y coordinates when the event occurred. The y coordinate has an extra value added to it to offset the tip window just below the cursor when it's displayed. The mouseExited() method disposes of the tip window and sets the tip window variable to null.

I've included a sample program (see Listing 3) that demonstrates using the tip window control. There are three requirements for using it:

  1. A TipWindowMouseAdapter object must be instantiated.
  2. A mouse listener must be added to every control that requires a tip window.
  3. Every control that requires a tip window must be named via the java.awt.Component setName() method.

The last requirement is the most important, as the given component names are used as keys in the properties file that contains the tip window help text. Figure 1 shows the contents of the properties file used in the sample program. I chose a simple naming scheme that assigns a zero-offset numerical value to each component as it was added to the layout. Figure 2 shows the program with a tip window displayed.

Figure 1 Figure 2
Figure 2:

Summary
The code presented here is fully encapsulated and dynamic. No code changes to the tip window classes are necessary when GUI controls are added to or deleted from a Java AWT program. The tip window can be used as a simple help mechanism for your Java program's GUI controls.

Tip Windows in an Applet
You can also create tip windows for an applet's GUI controls. Use the following code to retrieve the applet's java.awt.Frame reference:

public void init()
{
Object parent;

parent = getParent();
while (!(parent instanceof Frame))
parent = ((Component) parent).getParent();
}

You'll need to cast the java.lang.Object reference variable, parent, to a java.awt.Frame reference when calling the TipWindowMouseAdapter constructor. Also be aware that a warning banner will display on the applet's tip windows unless the applet is digitally signed.

I had mixed results creating tip windows for my applet's GUI controls. I created a JAR file containing all the necessary files (class and properties) since my ISP doesn't allow any files with a .properties extension. I launched the applet using Netscape Communicator 4.6 and kept receiving the following error: Applet exception: error: java.lang.ClassFormatError: Bad magic number. This error normally signifies that a class file is corrupt, most often because the file was incorrectly FTP'ed (i.e., binary mode wasn't specified on the transfer). Having checked that my FTP process was correct, I tried launching the applet again, this time using Netscape Communicator 4.7, and was successful - to a point. The previous error never manifested itself; however, the tip windows didn't display with a warning banner (as I expected) and their screen location was offset incorrectly, often nowhere near the control. I performed my next test with Microsoft's Internet Explorer version 4.0 (4.72.3110.8, to be exact). I didn't receive any errors, and the tip windows displayed - sort of. The problem with IE 4.0 is that the warning banner completely obscures the tip windows, rendering the control completely useless. Your mileage may vary with different versions of either browser.

Author Bio
Pat Paternostro is an associate partner with the Tri-Com Consulting Group located in Rocky Hill, Connecticut. Tri-Com provides programming services for a wide variety of development tasks.
He can be reached at: [email protected].

	

Listing 1: 

import java.awt.*; 
import java.awt.event.*; 
import java.util.*; 

public class TipWindow extends Window 
{ 
 private String message; 
 private int tipYCoord; 
 private final int slack = 4; 

 public TipWindow(Frame parent, String 
 message, int xCoord, int yCoord) 
 { 
  super(parent); 

  /* Set the message to display */ 
  this.message = message; 

  /* Set the tip window's background color */ 
  setBackground(new Color(255,255,220)); 

  /* Set the tip window's font */ 
  Font f = new 
  Font("Arial",Font.PLAIN,12); 
  setFont(f); 

  /* Retrieve the font's metrics */ 
  FontMetrics fm = getFontMetrics(f); 
  tipYCoord = fm.getAscent() + slack/2; 

  /* Set the tip window's size based on 
     the font metrics */ 
  setSize(fm.stringWidth(message) + 
  slack,fm.getHeight() + slack); 

  /* Set the tip window's location */ 
  setLocation(xCoord,yCoord); 

  /* Display the tip window */ 
  setVisible(true); 
 } 

 public void paint(Graphics g) 
 { 
  /* Draw the tip window's border */ 
  g.drawRect(0,0,getSize().width - 
  1,getSize().height - 1); 

  /* Display the message */ 
  g.drawString(message,slack/2,tipYCoord); 
 } 
} 

Listing 2: 

class TipWindowMouseAdapter extends MouseAdapter 
{ 
 private TipWindow tp; 
 private Frame parent; 
 private ResourceBundle rb; 

 public TipWindowMouseAdapter(Frame par- 
 ent, String propFile) 
 { 
  this.parent = parent; 
  try {rb =  ResourceBundle.get- 
  Bundle(propFile);} 
  catch(MissingResourceException mre){} 
 } 

 public void mouseEntered(MouseEvent evt) 
 { 
  Component comp = evt.getComponent(); 
  Point p = comp.getLocationOnScreen(); 

  try 
  { 
   if (rb != null) 
    tp = new TipWindow(parent,rb.get- 
    String(comp.getName()),p.x + 
    evt.getX(),p.y + evt.getY() + 20); 
  } 
  catch(MissingResourceException mre){} 
 } 

 public void mouseExited(MouseEvent evt) 
 { 
  if (tp != null) 
  { 
   tp.dispose(); 
   tp = null; 
  } 
 } 
} 

Listing 3: 

import java.awt.event.*; 
import java.awt.*; 

public class TipWindowTest { 

 public static void main(String args[]) { 
  new TipWindowTestFrame(); 
 } 
} 

class TipWindowTestFrame extends Frame { 
 Label lblUserId = new Label("User  Id:"); 
 Label lblPassword = new Label("Password:"); 
 TextField tfUserid = new TextField(10); 
 TextField tfPassword = new TextField(10); 
 Button ok = new Button("OK"); 
 Button cancel = new Button("Cancel"); 

 TipWindowTestFrame() { 
  super(); 

  /* Set the layout */ 
  setLayout(new GridLayout(3,2,20,20)); 

  /* Add components */ 
  add(lblUserId); 
  add(tfUserid); 
  add(lblPassword); 
  add(tfPassword); 
  add(ok); 
  add(cancel); 

  MouseListener ml = new TipWindow- 
  MouseAdapter(this,"helptext"); 

  /* Get the frame's components */ 
  Component[] comps = getComponents(); 

  /* Cycle through adding mouse listen- 
   er and naming components */ 
  for (int i = 0; i < comps.length; i++) 
  { 
   comps[i].addMouseListener(ml); 
   comps[i].setName("" + i); 
  } 

  /* Add the window listener */ 
  addWindowListener(new WindowAdapter() { 
   public void windowClosing(WindowEvent 
                           evt) { 
    dispose(); System.exit(0);}}); 

  /* Size the frame */ 
  pack(); 

  /* Center the frame */ 
  Dimension screenDim = Toolkit.getDe- 
  faultToolkit().getScreenSize(); 
  Rectangle frameDim = getBounds(); 
  setLocation((screenDim.width - frameD- 
  im.width) / 2,(screenDim.height - 
  frameDim.height) / 2); 

  /* Show the frame */ 
  setVisible(true); 
 } 
} 



 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.