Swing/ToolTipAfterMouseWheelEvent の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/ToolTipAfterMouseWheelEvent へ行く。
- Swing/ToolTipAfterMouseWheelEvent の差分を削除
--- 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 hreflang: href: https://java-swing-tips.blogspot.com/2022/01/fix-jtooltip-display-of-jlist-cells-to.html lang: en --- * Summary [#summary] `JScrollPane`内の`JList`を`MouseWheel`で移動した後に表示される`ToolTip`の対象セルとその位置に修正します。 #download(https://drive.google.com/uc?id=1wqY3utjMezRBlJ9j8WIest2ResTWWTMF) * Source Code Examples [#sourcecode] #code(link){{ JList<String> list1 = new JList<String>(model) { @Override public void updateUI() { super.updateUI(); setCellRenderer(new TooltipListCellRenderer<>()); } }; JScrollPane scroll1 = new JScrollPane(list1); scroll1.addMouseWheelListener(e -> { JScrollPane scrollPane = (JScrollPane) e.getComponent(); Component view = scrollPane.getViewport().getView(); MouseEvent event = SwingUtilities.convertMouseEvent(scrollPane, e, view); ToolTipManager.sharedInstance().mouseMoved(event); }); }} * Explanation [#explanation] - `Default` -- たとえば先頭の`0: 11111`セルにマウスカーソルを移動した直後にすばやくマウスホイールを下方向に回転して別セル上にマウスカーソルが配置された状態でもツールチップ表示される内容は`0: 11111`で、その表示位置も現在のマウスカーソル付近ではなく`JScrollPane`で隠されている`0: 11111`セルの位置になる -- マウスホイール対応以前の実装なのでマウス移動イベント以外でカーソル直下のセルが変化することは想定されていない -- `JTable`、`JTree`などでも同様 - `MouseWheelListener` -- 親`JScrollPane`に`MouseWheelListener`を追加し、ホイールイベントを`SwingUtilities.convertMouseEvent(...)`で`JList`ソースのマウスイベントに変換して`ToolTipManager.sharedInstance().mouseMoved(...)`で実行 -- `JToolTip`表示後、マウスカーソルを移動せずにマウスホイールのみ回転して直下のセルが変更された場合でも同位置でツールチップテキストの更新が可能 -- `ToolTipManager`では`MouseEvent`の`ID`は考慮せずに位置のみ使用しているのでイベントソースの変更のみで十分 -- [https://community.oracle.com/tech/developers/discussion/1353509/tooltips-the-mouse-wheel-and-jscrollpane Tooltips, the mouse wheel and JScrollPane — oracle-tech] - `getToolTipLocation` -- `JList#getToolTipText()`と`JList#getToolTipLocation()`をオーバーライドしてそれぞれ`MouseEvent#getPoint()`と`Component#getMousePosition()`(内部で`MouseInfo.getPointerInfo()`を使用)で取得したマウス位置が異なる場合は後者で取得したマウス位置で`MouseEvent`を再作成して実行 -- [[Screen上にあるMouseの位置を取得する>Swing/MouseInfo]] #code{{ 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; } } }} * Reference [#reference] - [https://community.oracle.com/tech/developers/discussion/1353509/tooltips-the-mouse-wheel-and-jscrollpane Tooltips, the mouse wheel and JScrollPane — oracle-tech] - [[JListのセル上にToolTipを表示する>Swing/ToolTipOnCellBounds]] - [[Screen上にあるMouseの位置を取得する>Swing/MouseInfo]] * コメント [#comment] * Comment [#comment] #comment #comment