1

I want to be able to display two BufferedImages on a component which then will be able to be moved around the component using mouse drags and also overlap one another if dragged over the top of the other image.

So far I have been able to display two BufferedImages on top of one another by simply placing them within their own JLabels and then both onto the same JPanel, however I'm afraid I may not be thinking about this in the correct way.

Any help, advice or examples on this would be very appreciated.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Mochi
  • 71
  • 1
  • 11
  • 2
    right there are three ways by using `AbsoluteLayout`, `OverlayLayout` and `DragLayout` (maybe author of DragLayout is around:-) – mKorbel Feb 01 '13 at 21:31
  • [Here](http://stackoverflow.com/questions/14273923/how-can-i-set-the-priority-mouse-listener/14276466#14276466) is my own an example of dragging components in/over a container/multiple containers (uses gasspane) – David Kroukamp Feb 02 '13 at 08:23

2 Answers2

2

For this kind of situation, I usually use a JLayeredPane (which uses no-layout, meaning that you have to call yourself setBounds() or setSize()/setLocation()) but which handles pretty well layering and seems quite fitted for dragging freely components.

Here is a small demo example (which displays 10 draggable images (always the same)). Code could be improved but it gives you already a pretty good impression of what you could do.

import java.awt.Color;
import java.awt.Component;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Random;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.SwingUtilities;

public class TestComponentDragging {

    private JLayeredPane contentPane;

    protected void initUI() throws MalformedURLException {
        JFrame frame = new JFrame(TestComponentDragging.class.getSimpleName());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        contentPane = new JLayeredPane();
        contentPane.setBackground(Color.WHITE);
        contentPane.setOpaque(true);
        frame.setContentPane(contentPane);
        frame.setSize(Toolkit.getDefaultToolkit().getScreenSize());
        frame.setExtendedState(frame.getExtendedState() | JFrame.MAXIMIZED_BOTH);
        frame.setVisible(true);
        ImageIcon image = new ImageIcon(new URL("http://www.lemondedemario.fr/images/dossier/bowser/bowser.png"));
        MouseDragger dragger = new MouseDragger();
        Random random = new Random();
        for (int i = 0; i < 10; i++) {
            JLabel draggableImage = new JLabel(image);
            draggableImage.setSize(draggableImage.getPreferredSize());
            draggableImage.setLocation(random.nextInt(contentPane.getWidth() - draggableImage.getWidth()),
                    random.nextInt(contentPane.getHeight() - draggableImage.getHeight()));

            dragger.makeDraggable(draggableImage);
            contentPane.add(draggableImage);
        }
        contentPane.repaint();
    }

    public static class MouseDragger extends MouseAdapter {
        private Point lastLocation;
        private Component draggedComponent;

        @Override
        public void mousePressed(MouseEvent e) {
            draggedComponent = e.getComponent();
            lastLocation = SwingUtilities.convertPoint(draggedComponent, e.getPoint(), draggedComponent.getParent());
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            Point location = SwingUtilities.convertPoint(draggedComponent, e.getPoint(), draggedComponent.getParent());
            if (draggedComponent.getParent().getBounds().contains(location)) {
                Point newLocation = draggedComponent.getLocation();
                newLocation.translate(location.x - lastLocation.x, location.y - lastLocation.y);
                newLocation.x = Math.max(newLocation.x, 0);
                newLocation.x = Math.min(newLocation.x, draggedComponent.getParent().getWidth() - draggedComponent.getWidth());
                newLocation.y = Math.max(newLocation.y, 0);
                newLocation.y = Math.min(newLocation.y, draggedComponent.getParent().getHeight() - draggedComponent.getHeight());
                draggedComponent.setLocation(newLocation);
                lastLocation = location;
            }
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            lastLocation = null;
            draggedComponent = null;
        }

        public void makeDraggable(Component component) {
            component.addMouseListener(this);
            component.addMouseMotionListener(this);
        }

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                try {
                    new TestComponentDragging().initUI();
                } catch (MalformedURLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
    }
}

The result (each "Bowser" can be freely moved/dragged within the frame with your mouse): The result

Guillaume Polet
  • 47,259
  • 4
  • 83
  • 117
  • I took the route of using a JLayeredPane as you suggested and it's working perfectly. Your example really gave me a good clear understanding of how to work with it as well. Thanks again for all your help. – Mochi Feb 02 '13 at 21:47
  • 1
    @MrBillyUK Remember tha using null-layout/absolute-layout should be only used in very particular conditions. Almost all cases require to use an appropriate LayoutManager. And even in this situation, a LayoutManager could still be used (but it would then be slightly less efficient). – Guillaume Polet Feb 02 '13 at 22:11
1

I would not use JLabels for displaying and interacting with images. You can do some of the stuff, but then you are suddenly limited.

I would rather define a JPanel, overwrite its paintComponent(Graphics g) method and draw the images using the Graphics object. This way, you can easily apply all the sort of transforms, handle mouse events to drag, resize, rotate,... them.

Dan D.
  • 32,246
  • 5
  • 63
  • 79