用Java拖放

时间:2013-01-24 10:50:42

标签: java swing drag-and-drop

我一直在网上搜索示例或如何使用java的拖放。我找到了一些,但所有示例只允许您拖动到特定位置,即另一个列表框或文本区域。 我想知道是否有办法将物品拖到jpanel或类似的容器上,让物品放在容器上的任何地方。

3 个答案:

答案 0 :(得分:2)

只要目标是您要拖动的项目支持的放置目标,就可以将其放到JPanel等容器中。

您可以控制拖放项目在放置位置的显示方式。如果您的面板覆盖{​​{1}},那么您可以根据需要绘制该项目。

答案 1 :(得分:2)

  

'是一种将项目拖入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 ) {
    }
}

答案 2 :(得分:1)

我用这种方式实现了Drag& Drop:

在Java 6中出现了实现Drag& Drop的非常方便的机制,但它确实有它的缺点。例如,您应该明确指定Drop Target,当您需要在Drop Target附近放置对象时,这不是很有用。同样在标准实现中,不保证监听器方法的执行顺序。我将告诉你实现更具扩展性的Drag& Drop的概念。

最初应将鼠标侦听器(Mouse Listener和MouseMotionListener)分配给所有拖动源。需要实现3种方法:鼠标单击对象的方法,在对象上按住鼠标按钮移动鼠标的方法(mouseMragListener中的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);
   }
});

因此,当您单击对象Drag& Drop开始时,移动鼠标时应移动对象,当您释放鼠标时,对象应更改其位置并移动到新容器。如果对象将在一个容器的框架中移动,则可以仅实现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来显示拖动的对象。

算法如下:

  • 点击该对象。

  • 获取对象的屏幕截图(请参阅how to make a screenshot)。 隐藏原始对象。

  • 在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);

    }
}

在此回复中,仅给出了实施的概念。

此信息取自我的文章:Frequently Asked Questions during Java applet development