TITLE:JFrameの外側でもドラッグアイコンを表示する
#navi(../)
RIGHT:Posted by [[aterai]] at 2012-08-06
*JFrameの外側でもドラッグアイコンを表示する [#c4f3f6cb]
ドラッグ中のカーソル位置をDragSourceMotionListenerで取得し、そこにアイコンを追加したWindowを移動することで、JFrameの外側でもドラッグアイコンを表示します。

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

//#screenshot
#ref(https://lh4.googleusercontent.com/-HM5QzW5AZlk/UB9iFlbSZMI/AAAAAAAABQM/fggojAo0b-E/s800/DragSourceMotionListener.png)

**サンプルコード [#f394f0f4]
#code{{
final JWindow window = new JWindow();
window.add(label);
window.setAlwaysOnTop(true);
com.sun.awt.AWTUtilities.setWindowOpaque(window, false); // JDK 1.6.0
//window.setBackground(new Color(0, true)); // JDK 1.7.0
DragSource.getDefaultDragSource().addDragSourceMotionListener(new DragSourceMotionListener() {
  @Override public void dragMouseMoved(DragSourceDragEvent dsde) {
    window.setLocation(dsde.getLocation());
    window.setVisible(true);
  }
});
}}

**解説 [#s38cbe68]
上記のサンプルでは、JPanel中に配置したJLabel(アイコン)をDrag&Dropで別のJPanelなど(親のJFrameが異なっても可)に移動することができます。ドラッグ中のJLabelは透明化したWindowに配置され、ドラッグに合わせてそのWindowを移動しているので、JFrameの外でもドラッグアイコンが表示可能になっています。
ドラッグ中のカーソル位置取得には、MouseMotionListener を使用する方法もありますが、このサンプルのような TransferHandlerを使ったドラッグではMouseMotionListenerでマウスイベントを取得することができないので、DefaultDragSource に DragSourceMotionListener を追加してドラッグ中のカーソル位置を取得しています。
-注: DragSourceDragEvent#getLocation()で取得できる位置は、スクリーン上でのマウス位置なので、MouseEvent#getPoint()の場合のようにSwingUtilities.convertPointToScreen(pt, c);で変換しなくて良い 

**参考リンク [#jda9a30f]
- [[JLayerを使ってJTabbedPaneのタブの挿入位置を描画する>Swing/DnDLayerTabbedPane]]

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