0

I've seen code of drag and drop .

Question1: how can we move image inside dropped panel (using mouse pointer) after image will be dropped. (destination of image, I want to be where where I release mouse. and then to change location too (using mouse will be better. or using buttons - but using mouse is better)

Question2: how can I change location after dropping end?

p.s I want here image to component.

first I drag and drop component. then change location using mouse pointer (move it).

here is code:

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
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.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.IOException;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestDnD {

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

    public TestDnD() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                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 JList list;

        public TestPane() {
            setLayout(new BorderLayout());
            list = new JList();
            DefaultListModel model = new DefaultListModel();
            model.addElement(new User("Shaun"));
            model.addElement(new User("Andy"));
            model.addElement(new User("Luke"));
            model.addElement(new User("Han"));
            model.addElement(new User("Liea"));
            model.addElement(new User("Yoda"));
            list.setModel(model);
            add(new JScrollPane(list), BorderLayout.WEST);

            DragGestureRecognizer dgr = DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
                            list,
                            DnDConstants.ACTION_COPY_OR_MOVE,
                            new DragGestureHandler(list));

            JPanel panel = new JPanel(new GridBagLayout());
            add(panel);

            DropTarget dt = new DropTarget(
                            panel,
                            DnDConstants.ACTION_COPY_OR_MOVE,
                            new DropTargetHandler(panel),
                            true);



        }

    }

    public static class User {

        private String name;        

        public User(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        @Override
        public String toString() {
            return name;
        }

    }

    public static class UserTransferable implements Transferable {

        public static final DataFlavor USER_DATA_FLAVOR = new DataFlavor(User.class, "User");
        private User user;

        public UserTransferable(User user) {
            this.user = user;
        }

        @Override
        public DataFlavor[] getTransferDataFlavors() {
            return new DataFlavor[]{USER_DATA_FLAVOR};
        }

        @Override
        public boolean isDataFlavorSupported(DataFlavor flavor) {
            return USER_DATA_FLAVOR.equals(flavor);
        }

        @Override
        public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
            Object value = null;
            if (USER_DATA_FLAVOR.equals(flavor)) {
                value = user;
            } else {
                throw new UnsupportedFlavorException(flavor);
            }
            return value;
        }

    }

    protected class DragGestureHandler implements DragGestureListener {

        private JList list;

        public DragGestureHandler(JList list) {
            this.list = list;
        }

        @Override
        public void dragGestureRecognized(DragGestureEvent dge) {
            Object selectedValue = list.getSelectedValue();
            if (selectedValue instanceof User) {
                User user = (User) selectedValue;

                Transferable t = new UserTransferable(user);
                DragSource ds = dge.getDragSource();
                ds.startDrag(dge, null, t, new DragSourceHandler());
            }

        }

    }

    protected class DragSourceHandler implements DragSourceListener {

        public void dragEnter(DragSourceDragEvent dsde) {
        }

        public void dragOver(DragSourceDragEvent dsde) {
        }

        public void dropActionChanged(DragSourceDragEvent dsde) {
        }

        public void dragExit(DragSourceEvent dse) {
        }

        public void dragDropEnd(DragSourceDropEvent dsde) {

            System.out.println("Drag ended...");

        }

    }

    protected class DropTargetHandler implements DropTargetListener {

        private JPanel panel;

        public DropTargetHandler(JPanel panel) {
            this.panel = panel;
        }

        public void dragEnter(DropTargetDragEvent dtde) {
            if (dtde.getTransferable().isDataFlavorSupported(UserTransferable.USER_DATA_FLAVOR)) {
                System.out.println("Accept...");
                dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
            } else {
                System.out.println("Drag...");
                dtde.rejectDrag();
            }
        }

        public void dragOver(DropTargetDragEvent dtde) {
        }

        public void dropActionChanged(DropTargetDragEvent dtde) {
        }

        public void dragExit(DropTargetEvent dte) {
        }

        public void drop(DropTargetDropEvent dtde) {
            System.out.println("Dropped...");
            if (dtde.getTransferable().isDataFlavorSupported(UserTransferable.USER_DATA_FLAVOR)) {
                Transferable t = dtde.getTransferable();
                if (t.isDataFlavorSupported(UserTransferable.USER_DATA_FLAVOR)) {
                    try {
                        Object transferData = t.getTransferData(UserTransferable.USER_DATA_FLAVOR);
                        if (transferData instanceof User) {
                            User user = (User) transferData;
                            dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                            panel.add(new JLabel(user.getName()));
                            panel.revalidate();
                            panel.repaint();
                        } else {
                            dtde.rejectDrop();
                        }
                    } catch (UnsupportedFlavorException ex) {
                        ex.printStackTrace();
                        dtde.rejectDrop();
                    } catch (IOException ex) {
                        ex.printStackTrace();
                        dtde.rejectDrop();
                    }
                } else {
                    dtde.rejectDrop();
                }
            }
        }

    }

}

Community
  • 1
  • 1
  • Your question is contradictive, you say you don't the object to be a component, but then you say you want to drag`n`drop component. As per your previous question on the subject, if the container you dropping onto doesn't know how to render images, then dropping a component is more suitable (and better supported) – MadProgrammer May 10 '13 at 09:34
  • yes. I need Images. not Component :-) I'll update my question –  May 10 '13 at 09:40
  • Why do you think you need images? You can add an image to a JLabel and then drag the label like any other component. – camickr May 10 '13 at 15:38

1 Answers1

3

This is a implementation of dragging, essentially, images between two like panes.

If you're going to throw in the restriction of not allowing the movement of Components, you are going to be stuck with ensure that the source and target containers know how to handle the drag and drop (and render the results)

This has taken the better part 4 hours, so before you hammer me with update requests, make sure you've made the effort to understand the code and implemented your own changes

The implementation wraps the Image in a DragImage class, that maintains information about the image's location within its container, this used to produce the drag image...

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
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.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

public class TestDnD {

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

    public TestDnD() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException ex) {
                    } catch (InstantiationException ex) {
                    } catch (IllegalAccessException ex) {
                    } catch (UnsupportedLookAndFeelException ex) {
                    }

                    JFrame frame = new JFrame("Test");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new GridLayout(0, 2, 10, 10));
                    ((JComponent) frame.getContentPane()).setBorder(new EmptyBorder(10, 10, 10, 10));

                    BufferedImage img = ImageIO.read(new File("issue376.jpg"));
                    ImagePane imagePane = new ImagePane();
                    imagePane.addImage(img);

                    frame.add(imagePane);
                    frame.add(new ImagePane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                    System.exit(0);
                }
            }

        });
    }

    public class ImagePane extends JPanel {

        private List<DragImage> images;
        private DragImages dropImages;
        private Point dragPoint;

        public ImagePane() {
            setBorder(new LineBorder(Color.GRAY));
            images = new ArrayList<>(25);

            DragGestureRecognizer dgr = DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
                            this,
                            DnDConstants.ACTION_COPY_OR_MOVE,
                            new DragGestureHandler(this));

            DropTarget dt = new DropTarget(
                            this,
                            DnDConstants.ACTION_COPY_OR_MOVE,
                            new DropTargetHandler(this),
                            true);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        public DragImage getImageAt(Point p) {
            DragImage at = null;
            for (DragImage di : images) {
                if (di.contains(p)) {
                    at = di;
                    break;
                }
            }
            return at;
        }

        protected boolean contains(Image image) {
            boolean contains = false;
            for (DragImage di : images) {
                if (di.getImage() == image) {
                    contains = true;
                    break;
                }
            }
            return contains;
        }

        public void addImage(Image image) {
            if (image != null) {
                if (!contains(image)) {
                    int x = (int) Math.round(Math.random() * getWidth());
                    int y = (int) Math.round(Math.random() * getHeight());
                    addImageAt(new Point(x, y), image);
                }
            }
        }

        public void addImageAt(Point p, Image image) {
            if (p != null && image != null) {
                if (!contains(image)) {
                    DragImage di = new DragImage(image, p);
                    images.add(di);
                    repaint();
                }
            }
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            for (DragImage di : images) {
                g2d.drawImage(di.getImage(), di.getLocation().x, di.getLocation().y, this);
            }
            if (dropImages != null) {
                g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
                Point offset = dropImages.getOffset();
                for (DragImage di : dropImages.getImages()) {
                    Point pp = new Point(dragPoint);
                    pp.x -= offset.getX();
                    pp.y -= offset.getY();
                    g2d.drawImage(di.getImage(), pp.x, pp.y, this);
                }
            }
            g2d.dispose();
        }

        public void removeImages(List list) {
            if (list != null && list.size() > 0) {
                for (Object obj : list) {
                    if (obj instanceof DragImage) {
                        removeImage((DragImage) obj);
                    }
                }
            }
        }

        public void removeImage(DragImage img) {
            images.remove(img);
            repaint();
        }

        protected void setDragImages(DragImages dragImages) {
            this.dropImages = dragImages;
            repaint();
        }

        public void addImagesAt(Point location, List images) {
            if (images != null && images.size() > 0) {
                for (Object obj : images) {
                    if (obj instanceof Image) {
                        Image img = (Image) obj;
                        addImageAt(location, img);
                        location.x += 10;
                        location.y += 10;
                        if (location.x >= getWidth()) {
                            location.x = 0;
                        }
                        if (location.y >= getHeight()) {
                            location.y = 0;
                        }
                    }
                }
            }
        }

        protected void addImages(DragImages dragImages) {
            for (DragImage di : dragImages.getImages()) {
                images.add(di);
            }
            repaint();
        }

        protected void addImagesAt(Point dropPoint, DragImages dragImages) {
            Point offset = dragImages.getOffset();
            for (DragImage di : dragImages.getImages()) {
                Point p = di.getLocation();
                p.x = dropPoint.x - offset.x;
                p.y = dropPoint.y - offset.y;
                images.add(di);
            }
            repaint();
        }

        protected void setDragPoint(Point location) {
            dragPoint = location;
            repaint();
        }

    }

    public static class ImageTransferable implements Transferable {

        public static final DataFlavor DRAG_IMAGE_DATA_FLAVOR = new DataFlavor(List.class, "Images");
        private DragImages dragImages;

        public ImageTransferable(DragImages dragImages) {
            this.dragImages = dragImages;
        }

        @Override
        public DataFlavor[] getTransferDataFlavors() {
            return new DataFlavor[]{DRAG_IMAGE_DATA_FLAVOR};
        }

        @Override
        public boolean isDataFlavorSupported(DataFlavor flavor) {
            return DRAG_IMAGE_DATA_FLAVOR.equals(flavor);
        }

        @Override
        public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
            return dragImages;
        }

    }

    public class DragImage {

        private Image image;
        private Point p;

        public DragImage(Image image, Point p) {
            this.image = image;
            this.p = p;
        }

        public Image getImage() {
            return image;
        }

        public Point getLocation() {
            return p;
        }

        public Dimension getSize() {
            return new Dimension(image.getWidth(null), image.getHeight(null));
        }

        public boolean contains(Point p) {
            return new Rectangle(getLocation(), getSize()).contains(p);
        }

    }

    public class DragImages {

        private Point offset;
        private List<DragImage> images;

        public DragImages(Point offset, DragImage... images) {
            this.offset = offset;
            this.images = Arrays.asList(images);
        }

        public Point getOffset() {
            return offset;
        }

        public List<DragImage> getImages() {
            return images;
        }

    }

    protected class DragGestureHandler implements DragGestureListener {

        private ImagePane imagePane;

        public DragGestureHandler(ImagePane list) {
            this.imagePane = list;
        }

        @Override
        public void dragGestureRecognized(DragGestureEvent dge) {
            DragImage di = imagePane.getImageAt(dge.getDragOrigin());
            if (di != null) {
                Point origin = dge.getDragOrigin();
                Point p = new Point();
                p.x = origin.x - di.getLocation().x;
                p.y = origin.y - di.getLocation().y;
                Transferable t = new ImageTransferable(new DragImages(p, di));
                imagePane.removeImage(di);
                DragSource ds = dge.getDragSource();
                ds.startDrag(
                                dge,
                                null,
                                t,
                                new DragSourceHandler(imagePane));
            }

        }

    }

    protected class DragSourceHandler implements DragSourceListener {

        private ImagePane pane;

        public DragSourceHandler(ImagePane pane) {
            this.pane = pane;
        }

        public void dragEnter(DragSourceDragEvent dsde) {
        }

        public void dragOver(DragSourceDragEvent dsde) {
            pane.repaint();
        }

        public void dropActionChanged(DragSourceDragEvent dsde) {
        }

        public void dragExit(DragSourceEvent dse) {
        }

        public void dragDropEnd(DragSourceDropEvent dsde) {
            if (!dsde.getDropSuccess()) {
                Transferable t = dsde.getDragSourceContext().getTransferable();
                if (t != null) {
                    try {
                        Object transferData = t.getTransferData(ImageTransferable.DRAG_IMAGE_DATA_FLAVOR);
                        if (transferData instanceof DragImages) {
                            DragImages di = (DragImages) transferData;
                            pane.addImages(di);
                        }
                    } catch (UnsupportedFlavorException | IOException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        }

    }

    protected class DropTargetHandler implements DropTargetListener {

        private ImagePane panel;

        public DropTargetHandler(ImagePane panel) {
            this.panel = panel;
        }

        public void dragEnter(DropTargetDragEvent dtde) {
            if (dtde.getTransferable().isDataFlavorSupported(ImageTransferable.DRAG_IMAGE_DATA_FLAVOR)) {
                dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
                updateDragImages(dtde);
            } else {
                dtde.rejectDrag();
            }
        }

        public void dragOver(DropTargetDragEvent dtde) {
            updateDragImages(dtde);
            panel.repaint();
        }

        public void dropActionChanged(DropTargetDragEvent dtde) {
        }

        public void dragExit(DropTargetEvent dte) {
            panel.setDragImages(null);
        }

        public void drop(DropTargetDropEvent dtde) {
            panel.setDragImages(null);
            if (dtde.getTransferable().isDataFlavorSupported(ImageTransferable.DRAG_IMAGE_DATA_FLAVOR)) {
                Transferable t = dtde.getTransferable();
                if (t.isDataFlavorSupported(ImageTransferable.DRAG_IMAGE_DATA_FLAVOR)) {
                    try {
                        Object transferData = t.getTransferData(ImageTransferable.DRAG_IMAGE_DATA_FLAVOR);
                        if (transferData instanceof DragImages) {
                            DragImages images = (DragImages) transferData;
                            dtde.dropComplete(true);
                            dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                            panel.addImagesAt(dtde.getLocation(), images);
                        } else {
                            dtde.rejectDrop();
                        }
                    } catch (UnsupportedFlavorException ex) {
                        ex.printStackTrace();
                        dtde.rejectDrop();
                    } catch (IOException ex) {
                        ex.printStackTrace();
                        dtde.rejectDrop();
                    }
                } else {
                    dtde.rejectDrop();
                }
            }
        }

        protected void updateDragImages(DropTargetDragEvent dtde) {
            panel.setDragImages(null);
            Transferable t = dtde.getTransferable();
            if (t != null) {
                try {
                    Object transferData = t.getTransferData(ImageTransferable.DRAG_IMAGE_DATA_FLAVOR);
                    if (transferData instanceof DragImages) {
                        panel.setDragPoint(dtde.getLocation());
                        panel.setDragImages((DragImages)transferData);
                    }
                } catch (UnsupportedFlavorException | IOException ex) {
                    ex.printStackTrace();
                }
            }
        }

    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • thank you! and I have the final question: the location of images are this: ath.round(Math.random() * getWidth()); can i set this images like an layout? for example , if I need to add Jbutton under the image, how to do this? should i set X,Y , does not I? is there another way to do this? I need another Java components above the image and under the image too. and what is the best way to add components to that layout? –  May 10 '13 at 12:23
  • Essentially, no. You've thrown out the mechanisms that would make this work. I would create a ImagePane that was responsible for a single image. I would add this to a "control panel" that would allow you add controls around it. It would the add these to the image container. This would mean yo would have to use component drag n drop, which actually, makes life a lot easier – MadProgrammer May 10 '13 at 20:49
  • Now I have another problem too :-))) after drag and drop, I want to resize my image (zoom in , zoom out ). can you give me an advice? –  May 13 '13 at 09:21
  • You have a number of options, AffineTransfomation is probably the easier one to get running. Take a look at [this](Should I add code individually to each button, or can I cater to each button press by a public method that is called whenever a button is pressed?) for a more detailed implementation – MadProgrammer May 13 '13 at 09:38
  • there is no link. can you give me a link of example. please. thanks –  May 13 '13 at 13:05
  • http://stackoverflow.com/questions/11959758/java-maintaining-aspect-ratio-of-jpanel-background-image/11959928#11959928 – MadProgrammer May 13 '13 at 19:45
  • 1
    @DavidKroukamp I have hundreds more :P – MadProgrammer Jun 28 '13 at 08:23