繁体   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