---
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));
      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;
      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