• 追加された行はこの色です。
  • 削除された行はこの色です。
---
title: MouseWheelEventを親のJScrollPaneに転送する
tags: [JScrollPane, JLayer, MouseWheelEvent]
author: aterai
pubdate: 2014-08-18T00:11:00+09:00
description: JLayerを使って、ネストするJScrollPaneへのMouseWheelEventを転送し、スクロールが継続するように設定します。
hreflang:
    href: http://java-swing-tips.blogspot.jp/2014/09/forward-mouse-wheel-scroll-event-in.html
    href: http://java-swing-tips.blogspot.com/2014/09/forward-mouse-wheel-scroll-event-in.html
    lang: en
---
* 概要 [#a29251c3]
`JLayer`を使って、ネストする`JScrollPane`への`MouseWheelEvent`を転送し、スクロールが継続するように設定します。

#download(https://lh4.googleusercontent.com/-Ax3sBgN85bo/U_DD4w3kEjI/AAAAAAAACLg/H0QTGo7hLH4/s800/WheelOverNestedScrollPane.png)

* サンプルコード [#ied9d98d]
#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) {
        main.dispatchEvent(SwingUtilities.convertMouseEvent(c, e, main));
      }
    }
  }
}
}}

* 解説 [#r2d3a46b]
デフォルトでは、`JScrollPane`をネストさせると、子`JScrollPane`内での`MouseWheelEvent`は、親`JScrollPane`には伝搬しません。

上記のサンプルでは、子`JScrollPane`のスクロールバーが最下部にあるなら下方向(最上部なら上方向)の`MouseWheelEvent`は親`JScrollPane`に転送する`LayerUI`を作成し、これを親`JScrollPane`の`JLayer<JScrollPane>`に適用しています。

* 参考リンク [#y6712f22]
- [[JScrollBarが最後までスクロールしたことを確認する>Swing/DetectScrollToBottom]]

* コメント [#xe15c26d]
#comment
#comment