0

I had created a frame and then panels in it. I had placed an image in one panel, now I need to drag that image to another panel. How could I do that. Please explain step by step as am a beginner.

Maroun
  • 94,125
  • 30
  • 188
  • 241
  • 3
    *"Please explain step by step"* Please consult tutorials that do just that. SO is a Q&A site. – Andrew Thompson Jun 28 '13 at 07:39
  • 1
    Also please avoid writing **i** when it's you (**I**). – Maroun Jun 28 '13 at 07:40
  • Please refer to this link. [Is it possible to have “movable”/“draggable” components like JButtons, JTextFields in a JFrame?][1] [1]: http://stackoverflow.com/questions/5052141/is-it-possible-to-have-movable-draggable-components-like-jbuttons-jtextfiel Hope this helps for you. – Praveen Kumar A X Jun 28 '13 at 07:46
  • i think my code helpful to u, refer this doc. http://docs.oracle.com/javase/tutorial/uiswing/dnd/intro.html – Naveen Kumar Alone Jun 28 '13 at 07:47
  • 1
    You could take a look at [this example](http://stackoverflow.com/questions/16438084/move-image-from-one-panel-to-another/16439731#16439731) – MadProgrammer Jun 28 '13 at 08:14

2 Answers2

8

Quick example using pure java, DragGestureListener, DropTargetAdapter and TransferHandler for DnD support of images on one panel to another:

Before any shape is clicked and dragged:

screenshot before any shapes are dragged onto the empty panel

after green shape is selected and dragged onto the empty panel above:

screenshot of the green shape dragged onto the empty panel

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("https://i.stack.imgur.com/gJmeJ.png")));
        JLabel label2 = new JLabel(new ImageIcon(new URL("https://i.stack.imgur.com/8BGfi.png")));
        JLabel label3 = new JLabel(new ImageIcon(new URL("https://i.stack.imgur.com/1lgtq.png")));

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

        ds.createDefaultDragGestureRecognizer(label2, DnDConstants.ACTION_COPY, dlistener);

        ds.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);
    }
}
David Kroukamp
  • 36,155
  • 13
  • 81
  • 138
  • Also see [this](http://stackoverflow.com/questions/14273923/how-can-i-set-the-priority-mouse-listener/14276466#14276466) answer for dragging/dropping support of Swing components. (close to end of my answer is the code with screenshot) – David Kroukamp Jun 28 '13 at 08:18
  • 1
    +1 and [this](http://stackoverflow.com/questions/16478413/move-component-after-drag-and-drop) ;) – MadProgrammer Jun 28 '13 at 08:19
  • 1
    still a fan of low-level dragging ?-) – kleopatra Jun 28 '13 at 08:27
  • @kleopatra Lol I somehow knew you would find this post and correct me on my correct low-level counter part :P. To be honest I was going to put your last code in, but i need to get back to studying and stackoverflow is stopping me, its like a drug :) – David Kroukamp Jun 28 '13 at 08:29
  • 1
    @user2530927 See [this](http://stackoverflow.com/a/17302430/1133011) example which omits the `DragGestureListener` for some higher-level implementation. – David Kroukamp Jun 28 '13 at 08:31
  • Thanks, this answer did solved my issue: And further: for custom data transfer, create a new DataFlavor(Class>, StringMimeTipe) – Marcos Vasconcelos Mar 18 '14 at 02:36
  • Is there any reason for using 3 `DragSource`s `ds1`, `ds2`, and `ds3`? It is also working fine with only `ds1`. – Muhammad Khuzaima Umair Jul 03 '22 at 04:02
  • @MuhammadKhuzaimaUmair probably, it might have been my lack of experience at the time – David Kroukamp Jul 06 '22 at 13:28
1
  1. There's probably any number of ways to achieve what you want. You could use the glass pane or JXLayer or you could
  2. stop treating the two panels as separate elements and more like they were just windows into a large virtual space.
  3. This example basically treats the parent component as the "virtual space" into which the two image panes are windows.
  4. They both share the same image and image location details. They, individual, convert the image location (which is in virtual coordinates) to local coordinates and draw as much of the image as would appear on them...
  5. Mouse control is maintained by the parent. This greatly simplifies the process, as it can notify both the panels simultaneously

and the code is...

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);
            }
        }
    }
}
Naveen Kumar Alone
  • 7,536
  • 5
  • 36
  • 57
  • Friday, comment day :-) The coordinates in setImageLocation should be in the coordiates of the ImagePanel: it cannot know which client did set it, assuming it was parent is a wild guess. The other way round, whoever sets the location, does know where it originated and can convert them safely into target coordinates – kleopatra Jun 28 '13 at 08:24