[英]Drag and Drop in Java
我一直在互聯網上搜索示例或如何使用Java的拖放功能。 我發現了一些,但是所有示例僅允許您拖動到特定位置,即另一個列表框或文本區域。 我想知道是否有一種方法可以將項目拖到jpanel或類似的容器上,讓該項目自由地放在容器上的任何位置。
只要目標是要拖動的項目的受支持的放置目標,就可以將其放置到JPanel
容器中。
您可以控制拖動的項目在放置位置的顯示方式。 如果您的面板覆蓋了paintComponent()
則可以繪制項目,但可以找到合適的項目。
'是將項目拖到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 ) {
}
}
我以這種方式實現了拖放:
Java 6中已經出現了用於拖放操作的非常方便的機制,但是它確實有其缺點。 例如,您應該明確指定放置目標,當您需要將對象放置在放置目標附近時,這不是很有用。 同樣在標准實現中,不能保證偵聽器方法的執行順序。 我將告訴您實現更可擴展的拖放的概念。
最初,應將鼠標偵聽器(Mouse Listener和MouseMotionListener)分配給所有“拖動源”。 它需要實現3種方法:在對象上單擊鼠標的方法,在對象上按住鼠標按鈕的同時移動鼠標的方法(MouseMotionListener中的mouseDragged)和鼠標上移方法。
偵聽器分配如下所示:
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);
}
});
因此,當您單擊對象時,“拖放”操作開始,當您移動鼠標時,該對象應被移動;當您釋放鼠標時,該對象應更改其位置,並被移動到新的容器中。 如果對象將在一個容器的框架中移動,則可以僅實現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上繪制對象的屏幕快照。
移動鼠標時,您需要根據新坐標重新繪制屏幕截圖。
釋放鼠標時,需要將對象放置在光標所在的容器上。
顯示原始對象。
通過這種方法,我們對放置光標以放置Drop的容器沒有任何依賴,並且相應地,該對象可以在任何地方“拖放”。
具有透明效果的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 applet開發期間的常見問題
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.