簡體   English   中英

用Java拖放

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM