• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:JDesktopPaneにJInternalFrameを吸着させる
#navi(../)
*JDesktopPaneにJInternalFrameを吸着させる [#t9488112]
>編集者:[[Terai Atsuhiro>terai]]~
作成日:2007-01-01~
更新日:&lastmod;
---
category: swing
folder: MagneticFrame
title: JDesktopPaneにJInternalFrameを吸着させる
tags: [DesktopManager, JDesktopPane, JInternalFrame]
author: aterai
pubdate: 2007-01-01T08:38:12+09:00
description: JDesktopPaneとJInternalFrameの距離が近くなった場合、これらを自動的に吸着させます。
image: https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTPnXoiDZI/AAAAAAAAAeQ/9SMGwoIqOi8/s800/MagneticFrame.png
---
* 概要 [#summary]
`JDesktopPane`と`JInternalFrame`の距離が近くなった場合、これらを自動的に吸着させます。

#contents
#download(https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTPnXoiDZI/AAAAAAAAAeQ/9SMGwoIqOi8/s800/MagneticFrame.png)

**概要 [#o18d56cf]
JDesktopPaneとJInternalFrameの距離が近くなった場合、これらを自動的に吸着させます。
* サンプルコード [#sourcecode]
#code(link){{
desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
desktop.setDesktopManager(new MagneticDesktopManager());

#screenshot
// ...
class MagneticDesktopManager extends DefaultDesktopManager {
  @Override public void dragFrame(JComponent frame, int x, int y) {
    Container c = SwingUtilities.getAncestorOfClass(JDesktopPane.class, frame);
    if (c instanceof JDesktopPane) {
      JDesktopPane desktop = (JDesktopPane) c;
      int e = x;
      int n = y;
      int w = desktop.getSize().width - frame.getSize().width - e;
      int s = desktop.getSize().height - frame.getSize().height - n;
      if (isNear(e) || isNear(n) || isNear(w) || isNear(s)) {
        super.dragFrame(frame, getX(e, w), getY(n, s));
      } else {
        super.dragFrame(frame, x, y);
      }
    }
  }

**サンプルコード [#o8501b2d]
 private class MagneticListener extends MouseInputAdapter {
   private final JInternalFrame frame;
   private final Point loc = new Point();
   private static final int d = 10;
   public MagneticListener(JInternalFrame frame) {
     this.frame = frame;
   }
   public void mousePressed(MouseEvent e) {
     Point p1 = frame.getLocation();
     Point p2 = SwingUtilities.convertPoint(frame, e.getPoint(), frame.getDesktopPane());
     loc.setLocation(p2.x-p1.x, p2.y-p1.y);
   }
   public void mouseDragged(MouseEvent e) {
     JDesktopPane desktop = frame.getDesktopPane();
     Point p = e.getPoint();
     Point pp = SwingUtilities.convertPoint(frame, p.x-loc.x, p.y-loc.y, desktop);
     int xx = desktop.getSize().width -frame.getSize().width -pp.x;
     int yy = desktop.getSize().height-frame.getSize().height-pp.y;
     if(Math.abs(pp.x)>=d && Math.abs(pp.y)>=d && Math.abs(xx)>=d && Math.abs(yy)>=d) return;
     desktop.getDesktopManager().dragFrame(
       frame,
       (pp.x<xx)?((Math.abs(pp.x)<d)?0:pp.x):((Math.abs(xx)<d)?xx+pp.x:pp.x),
       (pp.y<yy)?((Math.abs(pp.y)<d)?0:pp.y):((Math.abs(yy)<d)?yy+pp.y:pp.y));
   }
 }
  private static int getX(int e, int w) {
    return e < w ? isNear(e) ? 0 : e : isNear(w) ? w + e : e;
  }

-&jnlp;
-&jar;
-&zip;
  private static int getY(int n, int s) {
    return n < s ? isNear(n) ? 0 : n : isNear(s) ? s + n : n;
  }

**解説 [#oa45d781]
上記のサンプルでは、JDesktopPaneとJInternalFrameの距離が10pt以下になった場合、DesktopManager#.dragFrame(JInternalFrame,int,int)メソッドを使ってJInternalFrameの位置を変更することで、吸着を行っています。
  private static boolean isNear(int c) {
    return Math.abs(c) < 10;
  }
}
}}

//**参考リンク
**コメント [#y9744126]
* 解説 [#explanation]
`DesktopManager#dragFrame(JInternalFrame,int,int)`メソッドをオーバーライドすることで`JInternalFrame`の配置座標を調整しています。上記のサンプルでは、`JDesktopPane`と`JInternalFrame`の距離が`10px`以下になった場合、それぞれの辺が吸着するよう設定しています。

* 参考リンク [#reference]
- [https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/DefaultDesktopManager.html#dragFrame-javax.swing.JComponent-int-int- DefaultDesktopManager#dragFrame(...) (Java Platform SE 8)]

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