20
votes

In Swing, is there a way to define mouseover text (or tool tip text) for each item in a JComboBox?

5

5 Answers

22
votes

There is a much better way to do this than the ToolTipComboBox answer already given.

First, make a custom ListCellRenderer:

package com.example;

import javax.swing.*;
import java.awt.*;
import java.util.List;

public class ComboboxToolTipRenderer extends DefaultListCellRenderer {
    List<String> tooltips;

    @Override
    public Component getListCellRendererComponent(JList list, Object value,
                        int index, boolean isSelected, boolean cellHasFocus) {

        JComponent comp = (JComponent) super.getListCellRendererComponent(list,
                value, index, isSelected, cellHasFocus);

        if (-1 < index && null != value && null != tooltips) {
            list.setToolTipText(tooltips.get(index));
        }
        return comp;
    }

    public void setTooltips(List<String> tooltips) {
        this.tooltips = tooltips;
    }
}

Then use it like this:

JComboBox comboBox = new JComboBox();
ComboboxToolTipRenderer renderer = new ComboboxToolTipRenderer();
comboBox.setRenderer(renderer);
...
//make a loop as needed
comboBox.addItem(itemString);
tooltips.add(tooltipString);
...
renderer.setTooltips(tooltips);
8
votes

I like the simplicity of MountainX's solution but not the lack of encapsulation. An alternate solution which has more moving parts, but they are pretty simple and reusable.

An interface:

public interface ToolTipProvider {
    public String getToolTip();
}

A wrapper class:

public class ToolTipWrapper implements ToolTipProvider {
    final Object value;
    final String toolTip;

    public ToolTipWrapper(Object value, String toolTip) {
        this.value = value;
        this.toolTip = toolTip;
    }

    @Override
    public String getToolTip() {
        return toolTip; 
    }

    @Override
    public String toString() {
        return value.toString();
    }

}

And a variant of MountainX's renderer:

public class ToolTipRenderer extends DefaultListCellRenderer {

    @Override
    public Component getListCellRendererComponent(JList list, Object value,
            int index, boolean isSelected, boolean cellHasFocus) {
         JComponent component = (JComponent) super.getListCellRendererComponent(list, value, index, isSelected,
                cellHasFocus);
         String tip = null;
         if (value instanceof ToolTipProvider) {
             ToolTipProvider ttp = (ToolTipProvider) value;
             tip = ttp.getToolTip();
         }
         list.setToolTipText(tip);
         return component;
    }
}

with the adding now:

combobox.addItem(new ToolTipWrapper(itemString,tooltipString) );
3
votes

Here's little bit fixed code from an online example:

import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicComboBoxRenderer;

/**
 * @version 1.0 06/05/99
 */
public class ToolTipComboBox extends JFrame {

  /**
     * 
     */
    private static final long serialVersionUID = 2939624252688908292L;

String[] items = { "jw", "ja", "la" };

  String[] tooltips = { "Javanese ", "Japanese ", "Latin " };

  public ToolTipComboBox() {
    super("ToolTip ComboBox Example");

    JComboBox combo = new JComboBox(items);
    combo.setRenderer(new MyComboBoxRenderer());

    getContentPane().setLayout(new FlowLayout());
    getContentPane().add(combo);
  }

  class MyComboBoxRenderer extends BasicComboBoxRenderer {
    /**
     * 
     */
    private static final long serialVersionUID = 2746090194775905713L;

    @Override
    public Component getListCellRendererComponent(JList list, Object value,
        int index, boolean isSelected, boolean cellHasFocus) {
      if (isSelected) {
        setBackground(list.getSelectionBackground());
        setForeground(list.getSelectionForeground());
        if (-1 < index) {
          list.setToolTipText(tooltips[index]);
        }
      } else {
        setBackground(list.getBackground());
        setForeground(list.getForeground());
      }
      setFont(list.getFont());
      setText((value == null) ? "" : value.toString());
      return this;
    }
  }

  public static void main(String args[]) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}

    ToolTipComboBox frame = new ToolTipComboBox();
    frame.addWindowListener(new WindowAdapter() {
      @Override
    public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    frame.setSize(200, 140);
    frame.setVisible(true);
  }
}
3
votes

If your combo box is not editable, use setRenderer(ListCellRenderer). If it is editable, use setEditor(ComboBoxEditor), because:

The renderer is used if the JComboBox is not editable. If it is editable, the editor is used to render and edit the selected item.

0
votes

I've never tried it, but you should be able to define a ListCellRenderer, and have it return a JLabel or whatever with a tool tip.