• category: swing folder: ToolTipAfterMouseWheelEvent title: JListのセルのToolTipをMouseWheelEventに対応した表示位置に修正 tags: [JToolTip, JList, JScrollPane, MouseWheelListener, ToolTipManager] author: aterai pubdate: 2022-01-24T09:33:09+09:00 description: JScrollPane内のJListをMouseWheelで移動した後に表示されるToolTipの対象セルとその位置に修正します。 image: https://drive.google.com/uc?id=1wqY3utjMezRBlJ9j8WIest2ResTWWTMF

概要

JScrollPane内のJListをMouseWheelで移動した後に表示されるToolTipの対象セルとその位置に修正します。

サンプルコード

class TooltipList<E> extends JList<E> {
  protected TooltipList(ListModel<E> m) {
    super(m);
  }

  @Override public String getToolTipText(MouseEvent e) {
    Point p0 = e.getPoint();
    Point p1 = getMousePosition();
    if (p1 != null && !p1.equals(p0)) {
      int i = locationToIndex(p1);
      Rectangle cellBounds = getCellBounds(i, i);
      if (i >= 0 && cellBounds != null && cellBounds.contains(p1.x, p1.y)) {
        MouseEvent event = new MouseEvent(
            e.getComponent(),
            MouseEvent.MOUSE_MOVED,
            e.getWhen(),
            e.getModifiers(),
            p1.x,
            p1.y,
            e.getClickCount(),
            e.isPopupTrigger()
        );
        return super.getToolTipText(event);;
      }
    }
    return super.getToolTipText(e);
  }

  @Override public Point getToolTipLocation(MouseEvent e) {
    Point p0 = e.getPoint();
    Point p1 = getMousePosition();
    if (p1 != null && !p1.equals(p0)) {
      int i = locationToIndex(p1);
      Rectangle cellBounds = getCellBounds(i, i);
      if (i >= 0 && cellBounds != null && cellBounds.contains(p1.x, p1.y)) {
        return new Point(p1.x, p1.y + cellBounds.height);
      }
    }
    return null;
  }
}
View in GitHub: Java, Kotlin

解説

  • Default
    • たとえば先頭の0: 11111セルにマウスカーソルを移動した直後にすばやくマウスホイールを下方向に回転して別セル上にマウスカーソルが配置された状態でもツールチップ表示される内容は0: 11111で、その表示位置も現在のマウスカーソル付近ではなくJScrollPaneで隠されている0: 11111セルの位置になる
    • マウスホイール対応以前の実装なのでマウス移動イベント以外でカーソル直下のセルが変化することは想定されていない
    • JTableJTreeなどでも同様
  • MouseWheelListener
    • JScrollPaneMouseWheelListenerを追加し、ホイールイベントをSwingUtilities.convertMouseEvent(...)JListソースのマウスイベントに変換してToolTipManager.sharedInstance().mouseMoved(...)で実行
    • ToolTipManagerではMouseEventIDは考慮せずに位置のみ使用しているのでイベントソースの変更のみで十分
    • [Tooltips, the mouse wheel and JScrollPane ? oracle-tech https://community.oracle.com/tech/developers/discussion/1353509/tooltips-the-mouse-wheel-and-jscrollpane]
  • getToolTipLocation
    • JList#getToolTipText()JList#getToolTipLocation()をオーバーライドしてそれぞれMouseEvent#getPoint()Component#getMousePosition()で取得したマウス位置が異なる場合はComponent#getMousePosition()で取得したマウス位置でMouseEventを作成して実行

参考リンク

コメント