如何将图像从一个面板拖动到另一个面板

时间:2013-06-28 07:35:18

标签: java image swing drag-and-drop jpanel

我创建了一个框架,然后在其中创建了面板。我在一个面板中放置了一个图像,现在我需要将该图像拖到另一个面板上。我怎么能这样做请作为初学者逐步解释。

3 个答案:

答案 0 :(得分:6)

使用纯java,DragGestureListenerDropTargetAdapterTransferHandler的快速示例,用于DnD支持一个面板上的图像到另一个面板:

在点击并拖动任何形状之前:

enter image description here

选择绿色形状并将其拖到上面的空白面板上后:

enter image description here

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDropEvent;
import java.io.IOException;
import java.net.URL;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.TransferHandler;
import javax.swing.TransferHandler.TransferSupport;
import javax.swing.border.TitledBorder;

public class Test {

    public static void main(String[] args) {
        createAndShowJFrame();
    }

    public static void createAndShowJFrame() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {

                JFrame frame = createJFrame();
                frame.setVisible(true);

            }
        });
    }

    private static JFrame createJFrame() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        frame.setTitle("Test");

        JPanel panel = createEmptyJPanel();
        new MyDropTargetListener(panel);//this must be done or we wont be able to drop any image onto the empty panel

        frame.add(panel, BorderLayout.CENTER);

        try {
            frame.add(createJLabelPanel(), BorderLayout.SOUTH);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        frame.pack();

        return frame;
    }

    private static JPanel createEmptyJPanel() {
        final JPanel p = new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(300, 300);
            }
        };
        p.setBorder(new TitledBorder("Drag Image onto this panel"));

        TransferHandler dnd = new TransferHandler() {
            @Override
            public boolean canImport(TransferSupport support) {
                if (!support.isDrop()) {
                    return false;
                }
                //only Strings
                if (!support.isDataFlavorSupported(DataFlavor.imageFlavor)) {
                    return false;
                }
                return true;
            }

            @Override
            public boolean importData(TransferSupport support) {
                if (!canImport(support)) {
                    return false;
                }

                Transferable tansferable = support.getTransferable();
                Icon ico;
                try {
                    ico = (Icon) tansferable.getTransferData(DataFlavor.imageFlavor);
                } catch (Exception e) {
                    e.printStackTrace();
                    return false;
                }
                p.add(new JLabel(ico));
                return true;
            }
        };

        p.setTransferHandler(dnd);

        return p;
    }

    private static JPanel createJLabelPanel() throws Exception {
        JPanel panel = new JPanel();
        panel.setBorder(new TitledBorder("Drag Image from here to Panel above"));

        JLabel label1 = new JLabel(new ImageIcon(new URL("http://i.stack.imgur.com/gJmeJ.png")));
        JLabel label2 = new JLabel(new ImageIcon(new URL("http://i.stack.imgur.com/8BGfi.png")));
        JLabel label3 = new JLabel(new ImageIcon(new URL("http://i.stack.imgur.com/1lgtq.png")));

        MyDragGestureListener dlistener = new MyDragGestureListener();
        DragSource ds1 = new DragSource();
        ds1.createDefaultDragGestureRecognizer(label1, DnDConstants.ACTION_COPY, dlistener);

        DragSource ds2 = new DragSource();
        ds2.createDefaultDragGestureRecognizer(label2, DnDConstants.ACTION_COPY, dlistener);

        DragSource ds3 = new DragSource();
        ds3.createDefaultDragGestureRecognizer(label3, DnDConstants.ACTION_COPY, dlistener);

        panel.add(label1);
        panel.add(label2);
        panel.add(label3);
        return panel;
    }
}

class MyDropTargetListener extends DropTargetAdapter {

    private DropTarget dropTarget;
    private JPanel p;

    public MyDropTargetListener(JPanel panel) {
        p = panel;
        dropTarget = new DropTarget(panel, DnDConstants.ACTION_COPY, this, true, null);

    }

    @Override
    public void drop(DropTargetDropEvent event) {
        try {
            DropTarget test = (DropTarget) event.getSource();
            Component ca = (Component) test.getComponent();
            Point dropPoint = ca.getMousePosition();
            Transferable tr = event.getTransferable();

            if (event.isDataFlavorSupported(DataFlavor.imageFlavor)) {
                Icon ico = (Icon) tr.getTransferData(DataFlavor.imageFlavor);

                if (ico != null) {

                    p.add(new JLabel(ico));
                    p.revalidate();
                    p.repaint();
                    event.dropComplete(true);
                }
            } else {
                event.rejectDrop();
            }
        } catch (Exception e) {
            e.printStackTrace();
            event.rejectDrop();
        }
    }
}

class MyDragGestureListener implements DragGestureListener {

    @Override
    public void dragGestureRecognized(DragGestureEvent event) {
        JLabel label = (JLabel) event.getComponent();
        final Icon ico = label.getIcon();


        Transferable transferable = new Transferable() {
            @Override
            public DataFlavor[] getTransferDataFlavors() {
                return new DataFlavor[]{DataFlavor.imageFlavor};
            }

            @Override
            public boolean isDataFlavorSupported(DataFlavor flavor) {
                if (!isDataFlavorSupported(flavor)) {
                    return false;
                }
                return true;
            }

            @Override
            public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
                return ico;
            }
        };
        event.startDrag(null, transferable);
    }
}

答案 1 :(得分:1)

  1. 可能有很多方法可以达到你想要的效果。您可以使用玻璃窗格或JXLayer,也可以
  2. 停止将两个面板视为单独的元素,更像是将它们放入大型虚拟空间中。
  3. 此示例基本上将父组件视为两个图像窗格为窗口的“虚拟空间”。
  4. 它们共享相同的图像和图像位置详细信息。他们个人将图像位置(在虚拟坐标中)转换为局部坐标,并绘制尽可能多的图像......
  5. 鼠标控件由父级维护。这大大简化了流程,因为它可以同时通知两个面板
  6. 代码是......

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.GridLayout;
    import java.awt.Image;
    import java.awt.Point;
    import java.awt.Rectangle;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    import javax.swing.border.EmptyBorder;
    import javax.swing.border.LineBorder;
    
    public class CrossImage {
    
        public static void main(String[] args) {
            new CrossImage();
        }
    
        public CrossImage() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            private BufferedImage img;
            private ImagePane left;
            private ImagePane right;
            private Point imagePoint;
    
            public TestPane() {
                setBorder(new EmptyBorder(10, 10, 10, 10));
                setLayout(new GridLayout(0, 2, 10, 10));
                left = new ImagePane();
                right = new ImagePane();
                imagePoint = new Point(10, 10);
                left.setImageLocation(imagePoint);
                right.setImageLocation(imagePoint);
                try {
                    img = ImageIO.read(new File("Background.jpg"));
                    left.setImage(img);
                    right.setImage(img);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
                add(left);
                add(right);
    
                MouseAdapter mouseHandler = new MouseAdapter() {
                    private Point delta;
    
                    @Override
                    public void mousePressed(MouseEvent e) {
                        Point origin = e.getPoint();
                        Rectangle bounds = new Rectangle(imagePoint, new Dimension(img.getWidth(), img.getHeight()));
                        if (bounds.contains(origin)) {
                            delta = new Point(origin.x - imagePoint.x, origin.y - imagePoint.y);
                        }
                    }
    
                    @Override
                    public void mouseDragged(MouseEvent e) {
                        if (delta != null) {
                            imagePoint = e.getPoint();
                            imagePoint.translate(-delta.x, -delta.y);
                            left.setImageLocation(imagePoint);
                            right.setImageLocation(imagePoint);
                        }
                    }
    
                    @Override
                    public void mouseReleased(MouseEvent e) {
                        delta = null;
                    }
                };
    
                addMouseListener(mouseHandler);
                addMouseMotionListener(mouseHandler);
            }
        }
    
        public class ImagePane extends JPanel {
    
            private Image image;
            private Point imageLocation;
    
            public ImagePane() {
                setBorder(new LineBorder(Color.DARK_GRAY));
            }
    
            @Override
            public Dimension getPreferredSize() {
                return image == null ? super.getPreferredSize() : new Dimension(image.getWidth(this), image.getHeight(this));
            }
    
            public void setImage(Image image) {
                this.image = image;
                repaint();
            }
    
            public void setImageLocation(Point imageLocation) {
                this.imageLocation = imageLocation;
                repaint();
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                if (image != null && imageLocation != null) {
                    Point p = SwingUtilities.convertPoint(getParent(), imageLocation, this);
                    g.drawImage(image, p.x, p.y, this);
                }
            }
        }
    }
    

答案 2 :(得分:1)

希望这对你有所帮助。非常类似的问题和一个好的答案。

Is it possible to have “movable”/“draggable” components like JButtons, JTextFields in a JFrame?