• category: swing folder: ToolTipInComboBox title: JComboBoxの各アイテムやArrowButtonにそれぞれToolTipTextを設定する tags: [JComboBox, JToolTip, JLayer] author: aterai pubdate: 2017-04-24T14:34:47+09:00 description: JComboBoxの各リストアイテムやArrowButtonに、それぞれ異なるToolTipTextを設定します。 image: https://drive.google.com/uc?id=1-hvVHO5A6M8VTO8QPye3epe-ZazLLTzfDQ

概要

JComboBoxの各リストアイテムやArrowButtonに、それぞれ異なるToolTipTextを設定します。

サンプルコード

private static JComponent makeComboBox() {
  JComboBox<String> combo = new JComboBox<>(new String[] {"aaa", "bbbbb", "c"});
  combo.setRenderer(new DefaultListCellRenderer() {
    @Override public Component getListCellRendererComponent(
        JList<?> list, Object value, int index,
        boolean isSelected, boolean cellHasFocus) {
      Component c = super.getListCellRendererComponent(
          list, value, index, isSelected, cellHasFocus);
      if (c instanceof JComponent) {
        ((JComponent) c).setToolTipText(String.format("Item%d: %s", index, value));
      }
      return c;
    }
  });
  return new JLayer<>(combo, new ToolTipLayerUI<>());
}

class ToolTipLayerUI<V extends JComboBox> extends LayerUI<V> {
  @Override public void installUI(JComponent c) {
    super.installUI(c);
    if (c instanceof JLayer) {
      ((JLayer) c).setLayerEventMask(AWTEvent.MOUSE_MOTION_EVENT_MASK);
    }
  }
  @Override public void uninstallUI(JComponent c) {
    if (c instanceof JLayer) {
      ((JLayer) c).setLayerEventMask(0);
    }
    super.uninstallUI(c);
  }
  @Override protected void processMouseMotionEvent(MouseEvent e, JLayer<? extends V> l) {
    JComboBox<?> c = l.getView();
    if (e.getComponent() instanceof JButton) {
      c.setToolTipText("JButton");
    } else {
      c.setToolTipText("JComboBox: " + c.getSelectedItem());
    }
    super.processMouseMotionEvent(e, l);
  }
}
View in GitHub: Java, Kotlin

解説

  • JComboBox本体
    • JComboBox#setToolTipText(...)メソッドでToolTipTextを設定した場合、ArrowButtonや編集可の場合のJTextFieldなどのすべての子コンポーネントに同じテキストが設定される
      • 参考: BasicComboBoxUI#updateToolTipTextForChildren()
    • ドロップダウンリスト内のリストアイテムにToolTipTextは設定されない
  • リストアイテム
    • セルレンダラーにDefaultListCellRenderer#setToolTipText(...)メソッドでToolTipTextを設定
  • ArrowButton
    • JComboBox本体とは別のToolTipTextを設定するため、JLayerを使用
      • LayerUI#processMouseMotionEvent(...)をオーバーライドして、JButton上にマウスカーソルが入ったらJButton#setToolTipText(...)ToolTipTextを変更

  • JComboBoxのドロップダウンリストを開いた状態でツールチップを表示すると描画がおかしくなる場合がある
    • MetalLookAndFeelのみ
    • ドロップダウンリストがHeavyWeightWindowLightWeightWindowかは無関係

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class CustomJComboBoxTest2 {
  public JComponent makeUI() {
    JComboBox<String> box = new JComboBox<>();
    box.addItem("Item 1");
    box.addItem("Item 2");
    box.setToolTipText("TooTip");

    JPanel p = new JPanel(new BorderLayout());
    p.setBorder(BorderFactory.createEmptyBorder(60, 20, 60, 20));
    p.add(box);
    return p;
  }
  public static void main(String... args) {
    EventQueue.invokeLater(() -> {
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new CustomJComboBoxTest2().makeUI());
      f.setSize(320, 240);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}

コメント