Results 1 to 5 of 5

Thread: Drag & Drop

  1. #1
    kjkrum's Avatar
    kjkrum is offline Senior Member
    Join Date
    Apr 2011
    Location
    Tucson, AZ
    Posts
    1,060
    Rep Power
    6

    Default Drag & Drop

    I'm trying to add drag & drop support to JPanels by following the example at swing - Java - How to drag and drop JPanel with its components - Stack Overflow. That link is a little vague about how to tie it all together, and apparently I'm doing it wrong.

    Here are my classes:

    Java Code:
    package test;
    
    import java.awt.Color;
    import java.awt.Dimension;
    
    import javax.swing.JFrame;
    import javax.swing.SwingUtilities;
    
    // based on http://stackoverflow.com/a/11443501
    
    public class DnD implements Runnable {
    	
    	@Override
    	public void run() {
    		DraggableContainer container = new DraggableContainer();
    		container.add(createPanel(Color.RED));
    		container.add(createPanel(Color.BLUE));
    		
    		JFrame frame = new JFrame("DnD");
    		frame.add(container);
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		frame.pack();
    		frame.setVisible(true);
    	}
    	
    	private DraggablePanel createPanel(Color color) {
    		DraggablePanel panel = new DraggablePanel();
    		panel.setBackground(color);
    		panel.setPreferredSize(new Dimension(300, 500));
    		return panel;
    	}
    	
    	public static void main(String[] args) {
    		SwingUtilities.invokeLater(new DnD());
    	}
    }
    Java Code:
    package test;
    
    import java.awt.dnd.DnDConstants;
    import java.awt.dnd.DragGestureRecognizer;
    import java.awt.dnd.DragSource;
    
    import javax.swing.JPanel;
    
    public class DraggablePanel extends JPanel {
    	private static final long serialVersionUID = 1L;
    	
    	private DragGestureRecognizer dgr;
        private DragGestureHandler dragGestureHandler;
    
        @Override
        public void addNotify() {
            super.addNotify();
            if (dgr == null) {
                dragGestureHandler = new DragGestureHandler(this);
                dgr = DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
                        this,
                        DnDConstants.ACTION_MOVE,
                        dragGestureHandler);
            }
    
        }
    
        @Override
        public void removeNotify() {
            if (dgr != null) {
                dgr.removeDragGestureListener(dragGestureHandler);
                dragGestureHandler = null;
                dgr = null;
            }
            super.removeNotify();
        }
    
    }

    Java Code:
    package test;
    
    import java.awt.dnd.DnDConstants;
    import java.awt.dnd.DropTarget;
    
    import javax.swing.JPanel;
    import javax.swing.TransferHandler;
    
    public class DraggableContainer extends JPanel {
    	private static final long serialVersionUID = 1L;
    	
    	DropTarget dropTarget;
    	DropHandler dropHandler;
    	
    	public DraggableContainer() {
    		this.setTransferHandler(new TransferHandler(null));
    	}
    
    	@Override
    	public void addNotify() {
    		super.addNotify();
    		if(dropHandler == null) {
    			dropHandler = new DropHandler();
    			dropTarget = new DropTarget(this, DnDConstants.ACTION_MOVE, dropHandler, true);
    		}		
    	}
    		
    	@Override
    	public void removeNotify() {
    		if(dropHandler != null) {
    			dropTarget.removeDropTargetListener(dropHandler);
    			dropHandler = null;
    			dropTarget = null;
    		}
    		super.removeNotify();
    	}
    
    }
    The other classes are essentially identical to those in the SO comment.

    When I run the DnD class and start dragging one of the panels, I get this:

    Java Code:
    Exception in thread "AWT-EventQueue-0" java.awt.dnd.InvalidDnDOperationException: Cannot find top-level for the drag source component
    	at sun.awt.X11.XDragSourceContextPeer.startDrag(XDragSourceContextPeer.java:125)
    	at sun.awt.dnd.SunDragSourceContextPeer.startDrag(SunDragSourceContextPeer.java:130)
    	at java.awt.dnd.DragSource.startDrag(DragSource.java:318)
    	at java.awt.dnd.DragSource.startDrag(DragSource.java:415)
    	at test.DragGestureHandler.dragGestureRecognized(DragGestureHandler.java:48)
    	at java.awt.dnd.DragGestureRecognizer.fireDragGestureRecognized(DragGestureRecognizer.java:356)
    	at sun.awt.X11.XMouseDragGestureRecognizer.mouseDragged(XMouseDragGestureRecognizer.java:219)
    	at java.awt.Component.processMouseMotionEvent(Component.java:6336)
    	at javax.swing.JComponent.processMouseMotionEvent(JComponent.java:3285)
    	at java.awt.Component.processEvent(Component.java:6057)
    	at java.awt.Container.processEvent(Container.java:2045)
    	at java.awt.Component.dispatchEventImpl(Component.java:4649)
    	at java.awt.Container.dispatchEventImpl(Container.java:2103)
    	at java.awt.Component.dispatchEvent(Component.java:4475)
    	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4633)
    	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4314)
    	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4227)
    	at java.awt.Container.dispatchEventImpl(Container.java:2089)
    	at java.awt.Window.dispatchEventImpl(Window.java:2587)
    	at java.awt.Component.dispatchEvent(Component.java:4475)
    	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:675)
    	at java.awt.EventQueue.access$300(EventQueue.java:96)
    	at java.awt.EventQueue$2.run(EventQueue.java:634)
    	at java.awt.EventQueue$2.run(EventQueue.java:632)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:105)
    	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:116)
    	at java.awt.EventQueue$3.run(EventQueue.java:648)
    	at java.awt.EventQueue$3.run(EventQueue.java:646)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:105)
    	at java.awt.EventQueue.dispatchEvent(EventQueue.java:645)
    	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
    	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200)
    	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
    	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185)
    	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177)
    	at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)
    What am I missing?

    The official DnD tutorial trail is of no help. It's focused mainly on components that already support DnD, and some of its examples don't even work.
    Get in the habit of using standard Java naming conventions!

  2. #2
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

  3. #3
    kjkrum's Avatar
    kjkrum is offline Senior Member
    Join Date
    Apr 2011
    Location
    Tucson, AZ
    Posts
    1,060
    Rep Power
    6

    Default Re: Drag & Drop

    It's basically copied from that SO thread:

    Java Code:
    package test;
    
    import java.awt.Container;
    import java.awt.Cursor;
    import java.awt.datatransfer.Transferable;
    import java.awt.dnd.DragGestureEvent;
    import java.awt.dnd.DragGestureListener;
    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 javax.swing.JPanel;
    
    
    public class DragGestureHandler implements DragGestureListener, DragSourceListener {
    	
    	private final JPanel child;
    	private Container parent;
    	
    	public DragGestureHandler(JPanel child) {
    		if(child == null) throw new NullPointerException();
    		this.child = child;
    	}
    	
    	public JPanel getChild() {
    		return child;
    	}
    	
        public void setParent(Container parent) {
            this.parent = parent;
        }
    
        public Container getParent() {
            return parent;
        }
    
    	@Override
    	public void dragGestureRecognized(DragGestureEvent e) {
    		setParent(child.getParent());
    		parent.remove(child);
    		parent.invalidate();
    		parent.repaint();
    		
    		Transferable transferable = new JPanelTransferable(child);
    		DragSource ds = e.getDragSource();
            ds.startDrag(e, Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR), transferable, this);
    	}
    	
    	@Override
    	public void dragDropEnd(DragSourceDropEvent e) {
    		// put the panel back in its original container if the drop fails
    		// TODO save more details about its location in the container
            if (!e.getDropSuccess()) {
                getParent().add(child);
                getParent().invalidate();
                getParent().repaint();
            }
    		
    	}
    
    	@Override
    	public void dragEnter(DragSourceDragEvent e) {
    		// ignored
    		
    	}
    
    	@Override
    	public void dragExit(DragSourceEvent e) {
    		// ignored
    		
    	}
    
    	@Override
    	public void dragOver(DragSourceDragEvent e) {
    		// ignored		
    	}
    
    	@Override
    	public void dropActionChanged(DragSourceDragEvent e) {
    		// ignored
    		
    	}
    
    }
    Get in the habit of using standard Java naming conventions!

  4. #4
    kjkrum's Avatar
    kjkrum is offline Senior Member
    Join Date
    Apr 2011
    Location
    Tucson, AZ
    Posts
    1,060
    Rep Power
    6

    Default Re: Drag & Drop

    ZOMG... I just had a hunch that panned out. I changed the order of the statements in dragGestureRecognized, so it reads like this:

    Java Code:
    	@Override
    	public void dragGestureRecognized(DragGestureEvent e) {
    		Transferable transferable = new JPanelTransferable(child);
    		DragSource ds = e.getDragSource();
            	ds.startDrag(e, Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR), transferable, this);
            
    		setParent(child.getParent());
    		parent.remove(child);
    		parent.invalidate();
    		parent.repaint();
    	}
    And now it works! Or at least it doesn't crash. I can pick up the panels and drop them back where they were.
    Get in the habit of using standard Java naming conventions!

  5. #5
    DarrylBurke's Avatar
    DarrylBurke is offline Member
    Join Date
    Sep 2008
    Location
    Madgaon, Goa, India
    Posts
    11,188
    Rep Power
    19

    Default Re: Drag & Drop

    Moved from Advanced Java.

    db
    If you're forever cleaning cobwebs, it's time to get rid of the spiders.

Similar Threads

  1. drag and drop
    By Dean29126 in forum AWT / Swing
    Replies: 0
    Last Post: 01-18-2011, 07:24 AM
  2. drag and drop
    By Dean29126 in forum New To Java
    Replies: 0
    Last Post: 01-18-2011, 07:07 AM
  3. drag and drop - disable intra component drop
    By tomba in forum AWT / Swing
    Replies: 4
    Last Post: 12-09-2009, 01:01 PM
  4. Drag and drop
    By thayalan in forum AWT / Swing
    Replies: 1
    Last Post: 02-16-2009, 03:04 PM
  5. Drag and drop
    By abhivenugopal in forum JavaServer Pages (JSP) and JSTL
    Replies: 0
    Last Post: 01-30-2008, 02:10 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •