Tooltips in AWT and Swing

Tooltips in AWT and Swing

By Mark Volkmann, OCI Principal Software Engineer

May 1999


Tooltips are small windows of text that popup when the user leaves the mouse cursor over a component for a second or two. They are used to explain the functionality of the component.

Tooltips are an integral part of Swing components. They can be specified by calling the setToolTipText method as shown below.

deleteButton.setToolTipText("Deletes the selected grocery item");

Tooltips are not supported in AWT. However, the Window class can be used to add this capability.

The ToolTipManager class below does just that. To use it, add code like this, calling setToolTipText for each component that is to have a tooltip.

ToolTipManager.setToolTipText(deleteButton, "Deletes the selected grocery item");

The code below is heavily commented.  Feel free to use it as-is.

  1. package com.ociweb.awt;
  2.  
  3. import java.awt.*;
  4. import java.awt.event.*;
  5. import java.util.Hashtable;
  6.  
  7. /**
  8.  * Provides tooltips for AWT Components.
  9.  * @author R. Mark Volkmann, Object Computing, Inc.
  10.  */
  11. public class ToolTipManager implements MouseListener, Runnable {
  12.  
  13. /**
  14.   * The background color of the tooltips.
  15.   */
  16. private static final Color BACKGROUND_COLOR = new Color(200, 200, 255);
  17.  
  18. /**
  19.   * The number of milliseconds that the mouse must remain
  20.   * over a Component before its tooltip is displayed.
  21.   */
  22. private static final int WAIT_TIME = 1000; // milliseconds
  23.  
  24. /**
  25.   * Only one ToolTipManager object per application is needed
  26.   * so a singleton is created.
  27.   */
  28. private static ToolTipManager singleton = new ToolTipManager();
  29.  
  30. /**
  31.   * The Component over which the mouse is currently positioned.
  32.   */
  33. private Component currentComponent;
  34.  
  35. /**
  36.   * Mapping from Components to their tooltip text.
  37.   */
  38. private Hashtable componentToTipTable = new Hashtable();
  39.  
  40. /**
  41.   * The Component used to display the tooltip.
  42.   */
  43. private Label label = new Label();
  44.  
  45. /**
  46.   * A thread used to determine whether the cursor has remained
  47.   * over a Component long enough to display its tooltip.
  48.   */
  49. private Thread timerThread = new Thread(this);
  50.  
  51. /**
  52.   * The Window in which the tooltip is displayed.
  53.   */
  54. private Window window;
  55.  
  56. /**
  57.   * Creates a ToolTipManager.
  58.   * This is only invoked from this class since only a singleton is needed.
  59.   */
  60. private ToolTipManager() {
  61. label.setBackground(BACKGROUND_COLOR);
  62. timerThread.start();
  63. }
  64.  
  65. /**
  66.   * Creates the Window in which tooltips will be displayed.
  67.   */
  68. private void createWindow() {
  69. // Find the Frame parent of currentComponent.
  70. Component top = currentComponent;
  71. while (true) {
  72. Container parent = top.getParent();
  73. if (parent == null) break;
  74. top = parent;
  75. }
  76.  
  77.  
  78. // Use that Frame for the parent of the tooltip Window.
  79. window = new Window((Frame) top);
  80.  
  81.  
  82. window.add(label, BorderLayout.CENTER);
  83. }
  84.  
  85. /**
  86.   * Prevents the tooltip from being displayed if the timer hasn't expired
  87.   * and hides the tooltip window if it has.
  88.   */
  89. private void hideTip() {
  90. // Prevent the tooltip from being displayed
  91. // if the timer hasn't expired.
  92. timerThread.interrupt();
  93.  
  94.  
  95. // Hide the tooltip Window if it is already displayed.
  96. if (window != null) {
  97. window.setVisible(false);
  98. }
  99. }
  100.  
  101. /**
  102.   * Adds a tooltip to a given Component.
  103.   * @param component the Component
  104.   * @param tip the tooltip String
  105.   */
  106. public static void setToolTipText(Component component, String tip) {
  107. singleton.componentToTipTable.put(component, tip);
  108. component.addMouseListener(singleton);
  109. }
  110.  
  111. /**
  112.   * Determines which Component the mouse cursor is over and
  113.   * starts a thread to wait the appropriate amount of time
  114.   * before displaying its tooltip.
  115.   */
  116. public void mouseEntered(MouseEvent e) {
  117. currentComponent = (Component) e.getSource();
  118.  
  119.  
  120. // Notify the timerThread that the cursor is
  121. // now over a Component that has a tooltip.
  122. synchronized (this) {
  123. notify();
  124. }
  125. }
  126.  
  127. /**
  128.   * Interrupts the thread that is waiting to display the tooltip
  129.   * and hides the tooltip window.
  130.   */
  131. public void mouseExited(MouseEvent e) {
  132. if (e.getSource() == currentComponent) {
  133. hideTip();
  134. }
  135. }
  136.  
  137. /**
  138.   * Interrupts the thread that is waiting to display the tooltip
  139.   * and hides the tooltip window.
  140.  
  141.   */
  142. public void mousePressed(MouseEvent e) {
  143. if (e.getSource() == currentComponent) {
  144. hideTip();
  145. }
  146. }
  147.  
  148. // We don't need to do anything in these methods.
  149. public void mouseReleased(MouseEvent e) {}
  150. public void mouseClicked(MouseEvent e) {}
  151.  
  152. /**
  153.   * Removes a tooltip from a given Component.
  154.   * @param component the Component
  155.   */
  156. public static void removeToolTipText(Component component) {
  157. singleton.componentToTipTable.remove(component);
  158. component.removeMouseListener(singleton);
  159. }
  160.  
  161. /**
  162.   * Implementation of the timer thread.
  163.   * This waits the appropriate amount of time and then displays the tooltip.
  164.   */
  165. public synchronized void run() {
  166. while (true) {
  167. try {
  168. // Wait until notified that the cursor is over a Component
  169. // that has a tooltip.
  170. synchronized (this) {
  171. wait();
  172. }
  173.  
  174.  
  175. Thread.sleep(WAIT_TIME);
  176.  
  177.  
  178. // Get the tooltip text to be displayed.
  179. String tip =
  180. (String) componentToTipTable.get(currentComponent);
  181. label.setText(tip);
  182.  
  183.  
  184. if (window == null) {
  185. createWindow();
  186. }
  187. window.pack();
  188.  
  189.  
  190. // Place the tooltip directly below its Component.
  191. Rectangle bounds = currentComponent.getBounds();
  192. Point location = currentComponent.getLocationOnScreen();
  193. window.setLocation(location.x, location.y + bounds.height);
  194.  
  195.  
  196. window.setVisible(true);
  197. } catch (InterruptedException e) {
  198. // Don't break out of loop! Just wait for the mouse
  199. // to move over another component that has a tooltip.
  200. }
  201. }
  202. }
  203. }


Software Engineering Tech Trends (SETT) is a monthly publication featuring emerging trends in software engineering.

secret