---
category: swing
folder: ResizableComponents
title: JComponentをマウスで移動、リサイズ
tags: [JLayeredPane, MouseListener, MouseMotionListener, JComponent]
author: aterai
pubdate: 2008-05-19T13:41:14+09:00
description: JLayeredPaneに、マウスで移動、リサイズ可能なコンポーネントを追加します。
image: https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTRw-M85QI/AAAAAAAAAhs/BFyVP2IYoak/s800/ResizableComponents.png
---
* 概要 [#summary]
`JLayeredPane`に、マウスで移動、リサイズ可能なコンポーネントを追加します。

#download(https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTRw-M85QI/AAAAAAAAAhs/BFyVP2IYoak/s800/ResizableComponents.png)

* サンプルコード [#sourcecode]
#code(link){{
@Override public void mouseDragged(MouseEvent e) {
  if (startPos == null || startingBounds == null) return;
  Point p = SwingUtilities.convertPoint(
    e.getComponent(), e.getX(), e.getY(), null);
  int deltaX = startPos.x - p.x;
  int deltaY = startPos.y - p.y;
  int newX = getX();
  int newY = getY();
  int newW = getWidth();
  int newH = getHeight();

  JComponent parent = (JComponent) getParent();
  Rectangle parentBounds = parent.getBounds();
  Dimension min = new Dimension(50, 50);
  Dimension max = new Dimension(500, 500);

  switch (cursor) {
    case Cursor.N_RESIZE_CURSOR: {
      if (startingBounds.height + deltaY < min.height) {
        deltaY = -(startingBounds.height - min.height);
      } else if (startingBounds.height + deltaY > max.height) {
        deltaY = max.height - startingBounds.height;
      }
      if (startingBounds.y - deltaY < 0) {
        deltaY = startingBounds.y;
      }
      newX = startingBounds.x;
      newY = startingBounds.y - deltaY;
      newW = startingBounds.width;
      newH = startingBounds.height + deltaY;
      break;
    }
    case Cursor.NE_RESIZE_CURSOR: {
      if (startingBounds.height + deltaY < min.height) {
        deltaY = -(startingBounds.height - min.height);
// ...
}}

* 解説 [#explanation]
上記のサンプルでは、ツールバーやポップアップメニューから、移動、リサイズ可能な`JTable`や`JTree`を`JLayeredPane`(`JLayeredPane`のデフォルトレイアウトマネージャは`null`)に追加できます。

- リサイズボーダーの描画などは[https://github.com/santhosh-tekuri/MyBlog/tree/master/ResizableBorder MyBlog/ResizableBorder at master · santhosh-tekuri/MyBlog · GitHub]を参考
- マウスのドラッグによる移動、リサイズの最大値、最小値の制限などは`%JAVA_HOME%/src/javax/swing/plaf/basic/BasicInternalFrameUI.java`からの引用

----
- `JDK1.5`で`JLayeredPane#setComponentPopupMenu`を使う場合、以下のようなマウスリスナー(何も実行しない空のマウスリスナーでよい)を追加しておく必要がある?
#code{{
layer.setComponentPopupMenu(new MyPopupMenu());
layer.addMouseListener(new MouseAdapter() {});
}}

----
- `JDK1.6`では背面にある`JTable`のヘッダが前面にロールオーバーする場合がある
-- `JInternalFrame`が存在する場合は自動的に`JLayeredPane#isOptimizedDrawingEnabled()`が`false`になるよう変更されが、このサンプルでは`JTable`などを直接`JLayeredPane`に配置しているためこの現象が発生する
-- 以前のように`JLayeredPane#isOptimizedDrawingEnabled()`が常に`false`を返すようオーバーライドすれば回避可能
-- 参考: [[Component上に重ねて配置したダイアログの表示状態をアニメーション付きで切り替える>Swing/OverlayBorderLayout]]

#ref(https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTRzAZnaVI/AAAAAAAAAhw/t9TWz3YYv6U/s800/ResizableComponents1.png)

* 参考リンク [#reference]
- [https://github.com/santhosh-tekuri/MyBlog/tree/master/ResizableBorder MyBlog/ResizableBorder at master · santhosh-tekuri/MyBlog · GitHub]

* コメント [#comment]
#comment
- コピペミスで南西のコントロールポイントでリサイズが不可能になっていたバグを修正。 -- &user(aterai); &new{2024-07-26 (金) 02:59:29};
- コピペミスで南西のコントロールポイントでのリサイズが不可能になっていたバグを修正。 -- &user(aterai); &new{2024-07-26 (金) 02:59:29};
#comment