Swing/DragSourceMotionListener のバックアップの現在との差分(No.5)
TITLE:JFrameの外側でもドラッグアイコンを表示する
Posted by aterai at 2012-08-06
JFrameの外側でもドラッグアイコンを表示する
ドラッグ中のカーソル位置をDragSourceMotionListenerで取得し、そこにアイコンを追加したWindowを移動することで、JFrameの外側でもドラッグアイコンを表示します。- category: swing folder: DragSourceMotionListener title: JFrameの外側でもドラッグアイコンを表示する tags: [DragAndDrop, JWindow, ImageIcon, JFrame, JLabel] author: aterai pubdate: 2012-08-06T15:46:37+09:00 description: ドラッグ中のカーソル位置をDragSourceMotionListenerで取得し、そこにアイコンを追加したWindowを移動することで、JFrameの外側でもドラッグアイコンを表示します。 image:
概要
ドラッグ中のカーソル位置をDragSourceMotionListener
で取得し、そこにアイコンを追加したWindow
を移動することで、JFrame
の外側でもドラッグアイコンを表示します。
- &jnlp;
- &jar;
- &zip;
Screenshot
Advertisement
サンプルコード
サンプルコード
final JWindow window = new JWindow();
window.add(label);
#spandel
window.setAlwaysOnTop(true);
#spanend
#spandel
com.sun.awt.AWTUtilities.setWindowOpaque(window, false); // JDK 1.6.0
#spanend
#spandel
//window.setBackground(new Color(0, true)); // JDK 1.7.0
#spanend
#spanadd
// window.setAlwaysOnTop(true);
#spanend
#spanadd
// com.sun.awt.AWTUtilities.setWindowOpaque(window, false); // JDK 1.6.0
#spanend
#spanadd
window.setBackground(new Color(0x0, true)); // JDK 1.7.0
#spanend
DragSource.getDefaultDragSource().addDragSourceMotionListener(new DragSourceMotionListener() {
@Override public void dragMouseMoved(DragSourceDragEvent dsde) {
window.setLocation(dsde.getLocation());
window.setVisible(true);
}
});
View in GitHub: Java, Kotlin解説
上記のサンプルでは、JPanel 中に配置したJLabel(アイコン)を Drag & Drop で別の JPanel など(親の JFrame が異なる場合も可)に移動することができます。ドラッグ中の JLabel は透明化した Window に配置され、ドラッグに合わせてその Window を移動しているので、JFrame の外でもドラッグアイコンが表示可能になっています。 ドラッグ中のカーソル位置取得には、MouseMotionListener を使用する方法もありますが、このサンプルのような TransferHandler を使ったドラッグではMouseMotionListenerでマウスイベントを取得することができないので、DefaultDragSource に DragSourceMotionListener を追加してドラッグ中のカーソル位置を取得しています。解説
上記のサンプルでは、JPanel
中に配置されているアイコンなどを設定したJLabel
をDrag & Drop
で別のJPanel
(例えば親のJFrame
が異なる場合も可)に移動できます。JLabel
のドラッグ開始時に元の親JPanel
からそれを削除して透明化したWindow
に移し替え、ドラッグに合わせてWindow
自体を移動しているのでJFrame
の外でもドラッグアイコンが表示可能です。
- 注: DragSourceDragEvent#getLocation() で取得できる位置は、スクリーン上でのマウス位置なので、MouseEvent#getPoint() の場合のようにSwingUtilities.convertPointToScreen(pt, c); で変換しなくて良い
- ドラッグ中のカーソル位置取得には
MouseMotionListener
を使用する方法もあるが、このサンプルのようなTransferHandler
を使ったドラッグではMouseMotionListener
でマウスイベントを取得できないのでDefaultDragSource
にDragSourceMotionListener
を追加してドラッグ中のカーソル位置を取得している -
DragSourceDragEvent#getLocation()
で取得した位置はスクリーン座標系なのでそのままWindow#setLocation(...)
メソッドで使用可能 -
Point pt = tgtLabel.getLocation()
で取得したドラッグ対象JLabel
の位置は親コンポーネントの座標系なのでSwingUtilities.convertPointToScreen(pt, parent)
で変換する必要がある
参考リンク
参考リンク
コメント
- OSXなどの場合はどうなるか不明(テストしていない)。 -- aterai
- OSXでも表示しましたよ。ただクリックした時にアイコン周りに枠が表示されるのですが、その位置がアイコンとずれてます -- nsby?
- ありがとうございます。Bug ID: 4874070 invoking DragSource's startDrag with an Image renders no image on dragあたりの修正の詳しい内容がよく分かっていないので、逆にMac OS Xでは競合する(二重になる)のでは?と思っていました。「アイコン周りの枠」はオフセットを変更するか、クリックした時点でJPanelからは削除してしまえば、何とかなるかもしれません。 -- aterai
コメント
-
OSX
などの場合はどうなるか不明(テストしていない)。 -- aterai -
OSX
でも表示しましたよ。ただクリックした時にアイコン周りに枠が表示されるのですが、その位置がアイコンとずれてます -- nsby- ありがとうございます。Bug ID: 4874070 invoking DragSource's startDrag with an Image renders no image on dragあたりの修正の詳しい内容がよく分かっていないので、逆に
Mac OS X
では競合する(二重になる)のでは?と思っていました。「アイコン周りの枠」はオフセットを変更するか、クリックした時点でJPanel
からは削除してしまえば、何とかなるかもしれません。 -- aterai
- ありがとうございます。Bug ID: 4874070 invoking DragSource's startDrag with an Image renders no image on dragあたりの修正の詳しい内容がよく分かっていないので、逆に
-
Web Start
で起動すると、window.setAlwaysOnTop(true);
でAccessControlException
が発生するのを修正。 -- aterai - ドラッグ中カーソルが点滅するので、
dragMouseMoved
内で無駄にWindow#setVisible(true);
を実行しないように修正(TransferHandler#getSourceActions(...)
内でドラッグ開始時に一回だけ実行する)。 -- aterai