私はインターネットを検索して、例やJavaのドラッグアンドドロップの使用方法を見つけています。いくつか見つけましたが、すべての例では、特定の場所、つまり別のリストボックスまたはテキスト領域にドラッグすることしかできません。アイテムをjpanelまたは同様のコンテナにドラッグして、コンテナのどこにでも自由に配置できる方法があるかどうかを知りたいです。
3 に答える
'アイテムをjpanelにドラッグする方法です'
DropTargetをJPanelに設定できます。
public class MyDropTarget extends JPanel implements DropTargetListener {
private MyImage image;
private String text;
public MyDropTarget() {
setBackground(new Color(30,60,10));
this.setBorder( BorderFactory.createBevelBorder( BevelBorder.LOWERED, new Color(30,60,10).brighter(), new Color(30,60,10).darker() ) );
DropTarget dt = new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this, true, null);
this.setDropTarget( dt );
}
@Override
public void paintComponent( Graphics g ) {
super.paintComponent( g );
if( image != null && image.getImage() != null ) {
g.drawImage( image.getImage(), 0, 0, null );
if(image.isError()){
g.setColor(Color.BLACK);
g.drawString( text, 0, 0 );
}
}
}
public void dragEnter( DropTargetDragEvent dtde ) {
this.setBorder( BorderFactory.createBevelBorder( BevelBorder.RAISED, Color.RED.brighter(), Color.RED.darker() ) );
}
public void dragExit( DropTargetEvent dte ) {
this.setBorder( BorderFactory.createBevelBorder( BevelBorder.LOWERED, UIManager.getColor( "MenuBar.highlight" ), UIManager.getColor( "MenuBar.shadow" ) ) );
}
public void dragOver( DropTargetDragEvent dtde ) {
}
public void drop( DropTargetDropEvent dtde ) {
try {
text = (String) dtde.getTransferable().getTransferData( DataFlavor.stringFlavor );
image = (MyImage)dtde.getTransferable().getTransferData( DataFlavor.imageFlavor );
this.setBorder( BorderFactory.createBevelBorder( BevelBorder.LOWERED, new Color(30,60,10).brighter(), new Color(30,60,10).darker() ) );
dtde.dropComplete( true );
repaint();
} catch( UnsupportedFlavorException e ) {
e.printStackTrace();
} catch( IOException e ) {
e.printStackTrace();
}
this.setDropTarget( null );
}
public void dropActionChanged( DropTargetDragEvent dtde ) {
}
}
ターゲットがドラッグしているアイテムでサポートされているドロップターゲットである限り、のようなコンテナにドロップできますJPanel
。
ドラッグしたアイテムがドロップ位置に表示される方法を制御します。パネルがオーバーライドする場合paintComponent()
は、適切と思われる方法でアイテムをペイントできます。
私はこのようにドラッグアンドドロップを実装しました:
Drag&Dropを実装するための非常に便利なメカニズムがJava 6に登場しましたが、欠点があります。たとえば、ドロップターゲットを明示的に指定する必要があります。これは、ドロップターゲットの近くにオブジェクトを配置する必要がある場合にはあまり役に立ちません。また、標準の実装では、リスナーのメソッドの実行順序が保証されていません。より拡張性の高いドラッグアンドドロップを実装するための概念を説明します。
最初に、マウスリスナー(マウスリスナーとMouseMotionListener)をすべてのドラッグソースに割り当てる必要があります。オブジェクトをマウスクリックする方法、オブジェクト上でマウスボタンを押したままマウスを動かす方法(MouseMotionListenerのmouseDragged)、マウスアップ方法の3つの方法を実装する必要があります。
リスナーの割り当ては次のようになります。
component.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
//block click right mouse button
if (MouseEvent.BUTTON1 == e.getButton()) {
startDrag(e);
}
}
@Override
public void mouseReleased(MouseEvent e) {
//block click right mouse button
if (MouseEvent.BUTTON1 == e.getButton()) {
endDrag(e);
}
}
});
component.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
drag(e);
}
});
したがって、オブジェクトをクリックするとドラッグアンドドロップが開始され、マウスを移動するとオブジェクトが移動し、マウスを離すとオブジェクトの位置が変更されて新しいコンテナに移動する必要があります。オブジェクトが1つのコンテナのフレーム内で移動される場合は、mouseDragged()メソッドのみを実装できます。このメソッドでは、ドラッグされたオブジェクトの座標が変更されます。
@Override
public void mouseDragged(MouseEvent e) {
Point mouseLocation = e.getLocationOnScreen();
Component draggedComponent = (Component) e.getSource();
SwingUtilities.convertPointFromScreen(mouseLocation,
draggedComponent.getParent());
draggedComponent.setLocation(mouseLocation);
}
ただし、ドラッグされたオブジェクトの座標は、それが配置されているコンテナを基準にして設定できます。したがって、マウスを別のコンテナに移動する場合は、新しいコンテナにコンポーネントを追加したり、新しい座標を計算したりする必要があります。この方法はあまり美しく拡張性がないため、GlassPaneを使用してドラッグしたオブジェクトを表示することをお勧めします。
アルゴリズムは次のようになります。
オブジェクトをクリックします。
オブジェクトのスクリーンショットを取得します(スクリーンショットの作成方法を参照してください)。元のオブジェクトを非表示にします。
マウスの座標に基づいて、オブジェクトのスクリーンショットをglassPaneに描画します。
マウスを動かすときは、新しい座標に従ってスクリーンショットを再描画する必要があります。
マウスを離すときは、カーソルが置かれているコンテナにオブジェクトを配置する必要があります。
元のオブジェクトを表示します。
このアプローチでは、カーソルを置いてドロップするコンテナに依存することはなく、それに応じてオブジェクトをどこにでも「ドロップ」できます。
透明効果のあるGlassPane:
public class GhostGlassPane extends JPanel {
private final AlphaComposite composite;
private BufferedImage ghostImage = null;
private Point location = new Point(0, 0);
public GhostGlassPane() {
setOpaque(false);
composite = AlphaComposite.getInstance(AlphaComposite.
SRC_OVER, 0.7f);
}
public void paintComponent(Graphics g) {
if (ghostImage == null)
return;
Graphics2D g2 = (Graphics2D) g;
g2.setComposite(composite);
g2.drawImage(ghostImage, (int) (location.getX()),
(int) (location.getY()), null);
}
}
この応答では、実装の概念のみが示されています。
この情報は、私の記事「Javaアプレット開発中のよくある質問」から抜粋したものです。