• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:JWindowをマウスで移動
#navi(../)
#tags()
RIGHT:Posted by &author(aterai); at 2004-09-06
*JWindowをマウスで移動 [#g9940ceb]
JWindowなどのタイトルバーのないフレームをマウスで移動します。

-&jnlp;
-&jar;
-&zip;

//#screenshot
#ref(http://lh6.ggpht.com/_9Z4BYR88imo/TQTL8cG8F0I/AAAAAAAAAYY/vZfyqnyr6-I/s800/DragWindow.png)

**サンプルコード [#r3a65b7b]
#code(link){{
public void createSplashScreen(String path) {
  ImageIcon img = new ImageIcon(getClass().getResource(path));
  DragWindowListener dwl = new DragWindowListener();
  splashLabel = new JLabel(img);
  splashLabel.addMouseListener(dwl);
  splashLabel.addMouseMotionListener(dwl);
  splashScreen = new JWindow(getFrame());
  splashScreen.getContentPane().add(splashLabel);
  splashScreen.pack();
  splashScreen.setLocationRelativeTo(null);
}
class DragWindowListener extends MouseAdapter {
  private MouseEvent start;
  //private Point  loc;
  private Window window;
  @Override public void mousePressed(MouseEvent me) {
    start = me;
  }
  @Override public void mouseDragged(MouseEvent me) {
    if(window==null) {
      window = SwingUtilities.windowForComponent(me.getComponent());
    }
    Point eventLocationOnScreen = me.getLocationOnScreen();
    window.setLocation(eventLocationOnScreen.x - start.getX(),
                       eventLocationOnScreen.y - start.getY());
    //loc = window.getLocation(loc);
    //int x = loc.x - start.getX() + me.getX();
    //int y = loc.y - start.getY() + me.getY();
    //window.setLocation(x, y);
  }
}
}}

**解説 [#p1806440]
JWindowや、setUndecorated(true)したJFrameのようにタイトルバーのないフレームをマウスのドラッグで移動します。実際はJWindowに、MouseMotionListenerなどを実装したコンポーネントを追加しています。

上記のサンプルでは、Splash ScreenのJLabelにリスナーを追加し、これをJWindowに貼り付けてドラッグできるようにしています。

次に開くsetUndecorated(true)したJFrameでは、青いラベル部分をドラッグすることが出来ます。

----
- マルチディスプレイなどで、別画面に移動できないバグ?を修正。
-- ただし、Web Start のSandBox内では、以前と同じく画面の外に移動することができない?
--- JNLP のセキュリティに all-permissions を設定する必要がある

- Swing Tutorial の [http://docs.oracle.com/javase/tutorial/uiswing/examples/components/index.html#FrameDemo2 FrameDemo2]で試しても、同様?
-- "Look and feel decorated": 画面外に移動不可
-- "Window system decorated": 画面外に移動可能

**参考リンク [#n4c8a267]
-[[JInternalFrameをJFrameとして表示する>Swing/InternalFrameTitleBar]]
-[[JFrameのタイトルバーなどの装飾を独自のものにカスタマイズする>Swing/CustomDecoratedFrame]]

**コメント [#hfe1ff82]
- JLabel無しでJFrameを直接つかんで移動させようと,ソース中のDragWindowListenerをFrameの引数に指定してaddMouseListener(),addMouseMotionListener()に追加してみたのですが,うまく動きませんでした。ラベルではなくフレームを直接つかんで移動させるにはどうすればよいのでしょうか? -- [[hshs]] &new{2013-03-14 (木) 08:00:42};
-- ``frame.getContentPane().addMouseListener(dwl);...``と、``ContentPane``か``RootPane``に``DragWindowListener``を追加するか、以下のように``DragWindowListener``を変更するのはどうでしょうか? -- [[aterai]] &new{2013-03-14 (木) 13:53:25};

#code{{
//package example;
//-*- mode:java; encoding:utf-8 -*-
// vim:set fileencoding=utf-8:
//@homepage@
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MainPanel{
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    DragWindowListener dwl = new DragWindowListener();
    JFrame frame = new JFrame();
    frame.setUndecorated(true);
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.addMouseListener(dwl);
    frame.addMouseMotionListener(dwl);
    frame.setSize(320, 240);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}
class DragWindowListener extends MouseAdapter {
  private MouseEvent start;
  private Window window;
  @Override public void mousePressed(MouseEvent me) {
    start = me;
  }
  @Override public void mouseDragged(MouseEvent me) {
    if(window==null) {
      Object o = me.getSource();
      if(o instanceof Window) {
          window = (Window)o;
      }else if(window==null && o instanceof JComponent) {
          window = SwingUtilities.windowForComponent(me.getComponent());
        window = (Window)o;
      } else if(o instanceof JComponent) {
        window = SwingUtilities.windowForComponent(me.getComponent());
      }
    Point eventLocationOnScreen = me.getLocationOnScreen();
    window.setLocation(eventLocationOnScreen.x - start.getX(),
                       eventLocationOnScreen.y - start.getY());
    }
    start = me;
  }
  @Override public void mouseDragged(MouseEvent me) {
    if(window!=null) {
      Point eventLocationOnScreen = me.getLocationOnScreen();
      window.setLocation(eventLocationOnScreen.x - start.getX(),
                         eventLocationOnScreen.y - start.getY());
    }
  }
}
}}
- えーと、このソースは新たにJPanelを継承してるんですね、という事は結局、JFrame 自体をマウスドラッグでつかむことが出来ないということなんでしょうか? -- [[hshs]] &new{2013-03-15 (金) 11:08:52};
-- ``JFrame``の``ContentPane``に``JPanel``を継承したダミーコンポーネントをサンプルとして追加してるだけです。必要ないなら上記のように削除して(どこを削除したかはこのページ上にある「編集された箇所をみる」などで調べてください)調査してみるのがお手軽なのでオススメです。``JFrame``に追加したリスナーで``JFrame``の移動を行うことは可能ですが、本当に「``JFrame``自体をマウスドラッグでつかむことが出来ない」かどうかについては、内部での処理を追っていないのでよく分かりません。 -- [[aterai]] &new{2013-03-15 (金) 13:56:42};
- 返信ありがとうございます,最初のサンプル中のcreateAndShowGUI()内や,showFrame() や,start(JFrame frame)内などに,DragWindowListener dwl = new DragWindowListener();とframe.addMouseListener(dwl);と frame.addMouseMotionListener(dwl);を入れて見たりしたのですが動作しないのですが,これは何故なんでしょうか?、何か必要な命令が足りないのでしょうか。 -- [[hshs]] &new{2013-03-15 (金) 22:34:12};
-- 失礼、見落としてました。自分の環境(``JDK 1.7.0_17``, ``Windows 7``)では、特に問題なく動作(``Exception``なども出ていない)しています。環境と変更したソース自体をどこか(例えば https://gist.github.com/ とか)に投稿できますか? -- [[aterai]] &new{2013-03-18 (月) 15:34:53};
- あっ、動作しないというのは「JFrame自体をマウスドラッグでつかむことが出来ない」という意味で,通常の動作は問題ないです,上記のように追加変更して見たら,ラベルの部分だけでなく真ん中のフレーム部分を,マウスでドラッグしてつかんで移動させられるのかなと思ったのですが,実際つかんで移動させようとすると,Exception in thread "AWT-EventQueue-0" java.lang.NullPointerExceptionが出てきてつかめなかったので....。GitHubのアカウントは持ってないですw,環境はJDK1.7.0_15,win7,64bit,ソースは上の三行を追加してみただけです。 --  &new{2013-03-19 (火) 04:21:51};
-- 「上の三行を追加してみただけ」だと``DragWindowListener``が新しくなっていない(コメントの``DragWindowListener``になっていない)ので、``NullPointerException``が発生していると考えて良さそうです(ソースコードの行とかが分からないので推測ですが)。``src.zip``やリポジトリの``DragWindowListener``も更新した(ついでに上記のコメントの``DragWindowListener``もアップデート)ので、最新版で試してみてください。 -- [[aterai]] &new{2013-03-19 (火) 16:03:51};
-- 余談: gistってアカウント必要でしたっけ? -- [[aterai]] &new{2013-03-19 (火) 16:05:24};

#comment