概要

JSplitPaneに追加した子コンポーネントの余白などをドラッグしてDividerの位置を変更可能にするJLayerを設定します。

サンプルコード

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;
      splitPane.setDividerLocation(Math.max(0, dividerLocation + delta));
    }
  }
}
View in GitHub: Java, Kotlin

解説

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

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

参考リンク

コメント