Swing/WheelOverNestedScrollPane の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/WheelOverNestedScrollPane へ行く。
- Swing/WheelOverNestedScrollPane の差分を削除
--- category: swing folder: WheelOverNestedScrollPane title: MouseWheelEventを親のJScrollPaneに転送する tags: [JScrollPane, JLayer, MouseWheelEvent] author: aterai pubdate: 2014-08-18T00:11:00+09:00 description: JLayerを使って、ネストするJScrollPaneへのMouseWheelEventを転送し、スクロールが継続するように設定します。 image: https://lh4.googleusercontent.com/-Ax3sBgN85bo/U_DD4w3kEjI/AAAAAAAACLg/H0QTGo7hLH4/s800/WheelOverNestedScrollPane.png hreflang: href: https://java-swing-tips.blogspot.com/2014/09/forward-mouse-wheel-scroll-event-in.html lang: en --- * 概要 [#summary] `JLayer`を使って、ネストする`JScrollPane`への`MouseWheelEvent`を転送し、スクロールが継続するように設定します。 #download(https://lh4.googleusercontent.com/-Ax3sBgN85bo/U_DD4w3kEjI/AAAAAAAACLg/H0QTGo7hLH4/s800/WheelOverNestedScrollPane.png) * サンプルコード [#sourcecode] #code(link){{ class WheelScrollLayerUI extends LayerUI<JScrollPane> { @Override public void installUI(JComponent c) { super.installUI(c); if (c instanceof JLayer) { ((JLayer) c).setLayerEventMask(AWTEvent.MOUSE_WHEEL_EVENT_MASK); } } @Override public void uninstallUI(JComponent c) { if (c instanceof JLayer) { ((JLayer) c).setLayerEventMask(0); } super.uninstallUI(c); } @Override protected void processMouseWheelEvent( MouseWheelEvent e, JLayer<? extends JScrollPane> l) { Component c = e.getComponent(); int dir = e.getWheelRotation(); JScrollPane main = l.getView(); if (c instanceof JScrollPane && !c.equals(main)) { JScrollPane child = (JScrollPane) c; BoundedRangeModel m = child.getVerticalScrollBar().getModel(); int extent = m.getExtent(); int minimum = m.getMinimum(); int maximum = m.getMaximum(); int value = m.getValue(); if (value + extent >= maximum && dir > 0 || value <= minimum && dir < 0) { int ext = m.getExtent(); int min = m.getMinimum(); int max = m.getMaximum(); int value = m.getValue(); if (value + ext >= max && dir > 0 || value <= min && dir < 0) { main.dispatchEvent(SwingUtilities.convertMouseEvent(c, e, main)); } } } } }} * 解説 [#explanation] - ネストしている`JScrollPane`の子`JScrollPane`上でマウスイベントが発生した場合、`MouseWheelEvent`などのイベントは子`JScrollPane`内で消費されて親`JScrollPane`には伝搬しない - 上記のサンプルでは、子`JScrollPane`の縦スクロールバーが最下部にあるなら下方向(最上部なら上方向)の`MouseWheelEvent`は親`JScrollPane`に転送する`LayerUI`を作成し、これを親`JScrollPane`の`JLayer<JScrollPane>`に適用している * 参考リンク [#reference] - [[JScrollBarが最後までスクロールしたことを確認する>Swing/DetectScrollToBottom]] * コメント [#comment] #comment #comment