---
category: swing
folder: DividerLocationDragLayer
title: JSplitPaneに追加したコンポーネントをドラッグしてDividerの位置を変更する
tags: [JSplitPane, Divider, JLayer]
author: aterai
pubdate: 2016-05-30T00:20:49+09:00
description: JSplitPaneに追加した子コンポーネントの余白などをドラッグしてDividerの位置を変更可能にするJLayerを設定します。
image: https://lh3.googleusercontent.com/-XN3zaDJCb4g/V0sFzBq9QTI/AAAAAAAAOYQ/B2Y_715QARo0KbrhzgyG73OaYqKmeZwvgCCo/s800/DividerLocationDragLayer.png
---
* 概要 [#summary]
`JSplitPane`に追加した子コンポーネントの余白などをドラッグして`Divider`の位置を変更可能にする`JLayer`を設定します。

#download(https://lh3.googleusercontent.com/-XN3zaDJCb4g/V0sFzBq9QTI/AAAAAAAAOYQ/B2Y_715QARo0KbrhzgyG73OaYqKmeZwvgCCo/s800/DividerLocationDragLayer.png)

* サンプルコード [#sourcecode]
#code(link){{
class DividerLocationDragLayerUI extends LayerUI<JSplitPane> {
  private int dividerLocation;
  private final Point startPt = new Point();
  @Override public void installUI(JComponent c) {
    super.installUI(c);
    if (c instanceof JLayer) {
      ((JLayer) c).setLayerEventMask(
          AWTEvent.MOUSE_EVENT_MASK | 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 processMouseEvent(
      MouseEvent e, JLayer<? extends JSplitPane> l) {
    JSplitPane splitPane = l.getView();
    Component c = e.getComponent();
    if (splitPane.equals(SwingUtilities.getUnwrappedParent(c))
        && e.getID() == MouseEvent.MOUSE_PRESSED) {
      startPt.setLocation(SwingUtilities.convertPoint(c, e.getPoint(), splitPane));
      dividerLocation = splitPane.getDividerLocation();
    }
  }
  @Override protected void processMouseMotionEvent(
      MouseEvent e, JLayer<? extends JSplitPane> l) {
    JSplitPane splitPane = l.getView();
    Component c = e.getComponent();
    if (splitPane.equals(SwingUtilities.getUnwrappedParent(c))
        && e.getID() == MouseEvent.MOUSE_DRAGGED) {
      Point pt = SwingUtilities.convertPoint(c, e.getPoint(), splitPane);
      int delta = splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT
                  ? pt.x - startPt.x
                  : pt.y - startPt.y;
          ? pt.x - startPt.x : pt.y - startPt.y;
      splitPane.setDividerLocation(Math.max(0, dividerLocation + delta));
    }
  }
}
}}

* 解説 [#explanation]
上記のサンプルでは、`JSplitPane`の`Divider`をマウスでドラッグするだけでなく、`JSplitPane#setRightComponent(...)`などで追加した子コンポーネントをマウスでドラッグすることで、分割位置を変更できるように、`JSplitPane`にマウスイベントを取得する`LayerUI`を設定しています。

- ドラッグ可能になるのは、`JSplitPane`の子コンポーネントの余白(そのコンポーネントが別途マウスイベントを処理しない領域)
-- 例えば、マウスリスナーを追加していない`JLabel`はドラッグ可能、`JButton`などはドラッグ不可となる

* 参考リンク [#reference]
- [https://stackoverflow.com/questions/37462651/jsplitpane-small-border-but-big-grab-hitbox java - JSplitPane small border but big grab-hitbox - Stack Overflow]

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