Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8236955
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 7, 20262026-06-07T19:18:25+00:00 2026-06-07T19:18:25+00:00

I have a question about dragging and droping: I can drop labels, text or

  • 0

I have a question about dragging and droping:
I can drop labels, text or icon. But I want to drag and drop a JPanel with all its components (Label, Textbox,..etc).

How can I do this ?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-07T19:18:27+00:00Added an answer on June 7, 2026 at 7:18 pm

    This solution works. Some cavets to start with.

    I didn’t use the TransferHandler API. I don’t like it, it’s too restrictive, but that’s a personal thing (what it does, it does well), so this might not meet your expectations.

    I was testing with BorderLayout. If you want to use other layouts, you’re going to have to try and figure that out. The DnD subsystem does provide information about the mouse point (when moving and dropping).

    So what do we need:

    A DataFlavor. I chose to do this because it allows a greater deal of restriction

    public class PanelDataFlavor extends DataFlavor {
    
        // This saves me having to make lots of copies of the same thing
        public static final PanelDataFlavor SHARED_INSTANCE = new PanelDataFlavor();
    
        public PanelDataFlavor() {
    
            super(JPanel.class, null);
    
        }
    
    }
    

    A Transferable. Some kind of wrapper that wraps the data (our JPanel) up with a bunch of DataFlavors (in our case, just the PanelDataFlavor)

    public class PanelTransferable implements Transferable {
    
        private DataFlavor[] flavors = new DataFlavor[]{PanelDataFlavor.SHARED_INSTANCE};
        private JPanel panel;
    
        public PanelTransferable(JPanel panel) {
            this.panel = panel;
        }
    
        @Override
        public DataFlavor[] getTransferDataFlavors() {
            return flavors;
        }
    
        @Override
        public boolean isDataFlavorSupported(DataFlavor flavor) {
    
            // Okay, for this example, this is overkill, but makes it easier
            // to add new flavor support by subclassing
            boolean supported = false;
    
            for (DataFlavor mine : getTransferDataFlavors()) {
    
                if (mine.equals(flavor)) {
    
                    supported = true;
                    break;
    
                }
    
            }
    
            return supported;
    
        }
    
        public JPanel getPanel() {
    
            return panel;
    
        }
    
        @Override
        public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
    
            Object data = null;
            if (isDataFlavorSupported(flavor)) {
    
                data = getPanel();
    
            } else {
    
                throw new UnsupportedFlavorException(flavor);
    
            }
    
            return data;
    
        }
    
    }
    

    A “DragGestureListener”

    For this, I created a simple DragGestureHandler that takes a “JPanel” as the content to be dragged. This allows the gesture handler to become self managed.

    public class DragGestureHandler implements DragGestureListener, DragSourceListener {
    
        private Container parent;
        private JPanel child;
    
        public DragGestureHandler(JPanel child) {
    
            this.child = child;
    
        }
    
        public JPanel getPanel() {
            return child;
        }
    
        public void setParent(Container parent) {
            this.parent = parent;
        }
    
        public Container getParent() {
            return parent;
        }
    
        @Override
        public void dragGestureRecognized(DragGestureEvent dge) {
    
            // When the drag begins, we need to grab a reference to the
            // parent container so we can return it if the drop
            // is rejected
            Container parent = getPanel().getParent();
    
            setParent(parent);
    
            // Remove the panel from the parent.  If we don't do this, it
            // can cause serialization issues.  We could overcome this
            // by allowing the drop target to remove the component, but that's
            // an argument for another day
            parent.remove(getPanel());
    
            // Update the display
            parent.invalidate();
            parent.repaint();
    
            // Create our transferable wrapper
            Transferable transferable = new PanelTransferable(getPanel());
    
            // Start the "drag" process...
            DragSource ds = dge.getDragSource();
            ds.startDrag(dge, Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR), transferable, this);
    
        }
    
        @Override
        public void dragEnter(DragSourceDragEvent dsde) {
        }
    
        @Override
        public void dragOver(DragSourceDragEvent dsde) {
        }
    
        @Override
        public void dropActionChanged(DragSourceDragEvent dsde) {
        }
    
        @Override
        public void dragExit(DragSourceEvent dse) {
        }
    
        @Override
        public void dragDropEnd(DragSourceDropEvent dsde) {
    
            // If the drop was not successful, we need to
            // return the component back to it's previous
            // parent
            if (!dsde.getDropSuccess()) {
    
                getParent().add(getPanel());
    
                getParent().invalidate();
                getParent().repaint();
    
            }
        }
    }
    

    Okay, so that’s basics. Now we need to wire it all together…

    So, in the panel I want to drag, I added:

        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();
    
        }
    

    The reason for using the add/remove notify in this way is to keep the system clean. It helps prevent events from been delivered to our component when we no longer need them. It also provides automatic registration. You may wish to use your own “setDraggable” method.

    That’s the drag side, now for the drop side.

    First, we need a DropTargetListener:

    public class DropHandler implements DropTargetListener {
    
        @Override
        public void dragEnter(DropTargetDragEvent dtde) {
    
            // Determine if we can actually process the contents coming in.
            // You could try and inspect the transferable as well, but 
            // there is an issue on the MacOS under some circumstances
            // where it does not actually bundle the data until you accept the
            // drop.
            if (dtde.isDataFlavorSupported(PanelDataFlavor.SHARED_INSTANCE)) {
    
                dtde.acceptDrag(DnDConstants.ACTION_MOVE);
    
            } else {
    
                dtde.rejectDrag();
    
            }
    
        }
    
        @Override
        public void dragOver(DropTargetDragEvent dtde) {
        }
    
        @Override
        public void dropActionChanged(DropTargetDragEvent dtde) {
        }
    
        @Override
        public void dragExit(DropTargetEvent dte) {
        }
    
        @Override
        public void drop(DropTargetDropEvent dtde) {
    
            boolean success = false;
    
            // Basically, we want to unwrap the present...
            if (dtde.isDataFlavorSupported(PanelDataFlavor.SHARED_INSTANCE)) {
    
                Transferable transferable = dtde.getTransferable();
                try {
    
                    Object data = transferable.getTransferData(PanelDataFlavor.SHARED_INSTANCE);
                    if (data instanceof JPanel) {
    
                        JPanel panel = (JPanel) data;
    
                        DropTargetContext dtc = dtde.getDropTargetContext();
                        Component component = dtc.getComponent();
    
                        if (component instanceof JComponent) {
    
                            Container parent = panel.getParent();
                            if (parent != null) {
    
                                parent.remove(panel);
    
                            }
    
                            ((JComponent)component).add(panel);
    
                            success = true;
                            dtde.acceptDrop(DnDConstants.ACTION_MOVE);
    
                            invalidate();
                            repaint();
    
                        } else {
    
                            success = false;
                            dtde.rejectDrop();
    
                        }
    
                    } else {
    
                        success = false;
                        dtde.rejectDrop();
    
                    }
    
                } catch (Exception exp) {
    
                    success = false;
                    dtde.rejectDrop();
                    exp.printStackTrace();
    
                }
    
            } else {
    
                success = false;
                dtde.rejectDrop();
    
            }
    
            dtde.dropComplete(success);
    
        }
    
    }
    

    Finally, we need to register the drop target with interested parties… In those containers capable of supporting the drop, you want to add

    DropTarget dropTarget;
    DropHandler dropHandler;
    
    .
    .
    .
    
    dropHandler = new DropHandler();
    dropTarget = new DropTarget(pnlOne, DnDConstants.ACTION_MOVE, dropHandler, true);
    

    Personally, I initialise in the addNotify and dispose in the removeNotify

    dropTarget.removeDropTargetListener(dropHandler);
    

    Just a quick note on addNotify, I have had this been called a number of times in succession, so you may want to double-check that you haven’t already set up the drop targets.

    That’s it.

    You may also find some of the following of interest

    http://rabbit-hole.blogspot.com.au/2006/05/my-drag-image-is-better-than-yours.html

    http://rabbit-hole.blogspot.com.au/2006/08/drop-target-navigation-or-you-drag.html

    http://rabbit-hole.blogspot.com.au/2006/04/smooth-jlist-drop-target-animation.html

    It would be waste not to check them, even if just out of interest.

    2018 Update

    So, after 4 years since the original code was written, there seems to have been some changes into how the API works, at least under MacOS, which are causing a number of issues .

    First DragGestureHandler was causing a NullPointerException when DragSource#startDrag was been called. This seems to be related to setting the container’s parent reference to null (by removing it from the parent container).

    So, instead, I modified the dragGestureRecognized method to remove the panel from the parent AFTER DragSource#startDrag was called…

    @Override
    public void dragGestureRecognized(DragGestureEvent dge) {
        // When the drag begins, we need to grab a reference to the
        // parent container so we can return it if the drop
        // is rejected
        Container parent = getPanel().getParent();
        System.out.println("parent = " + parent.hashCode());
        setParent(parent);
    
        // Remove the panel from the parent.  If we don't do this, it
        // can cause serialization issues.  We could overcome this
        // by allowing the drop target to remove the component, but that's
        // an argument for another day
        // This is causing a NullPointerException on MacOS 10.13.3/Java 8
        //      parent.remove(getPanel());
        //      // Update the display
        //      parent.invalidate();
        //      parent.repaint();
    
        // Create our transferable wrapper
        System.out.println("Drag " + getPanel().hashCode());
        Transferable transferable = new PanelTransferable(getPanel());
        // Start the "drag" process...
        DragSource ds = dge.getDragSource();
        ds.startDrag(dge, null, transferable, this);
    
        parent.remove(getPanel());
        // Update the display
        parent.invalidate();
        parent.repaint();
    }
    

    I also modified the DragGestureHandler#dragDropEnd method

    @Override
    public void dragDropEnd(DragSourceDropEvent dsde) {
        // If the drop was not successful, we need to
        // return the component back to it's previous
        // parent
        if (!dsde.getDropSuccess()) {
            getParent().add(getPanel());
        } else {
            getPanel().remove(getPanel());
        }
        getParent().invalidate();
        getParent().repaint();
    }
    

    And DropHandler#drop

    @Override
    public void drop(DropTargetDropEvent dtde) {
        boolean success = false;
        // Basically, we want to unwrap the present...
        if (dtde.isDataFlavorSupported(PanelDataFlavor.SHARED_INSTANCE)) {
            Transferable transferable = dtde.getTransferable();
            try {
                Object data = transferable.getTransferData(PanelDataFlavor.SHARED_INSTANCE);
                if (data instanceof JPanel) {
                    JPanel panel = (JPanel) data;
                    DropTargetContext dtc = dtde.getDropTargetContext();
                    Component component = dtc.getComponent();
                    if (component instanceof JComponent) {
                        Container parent = panel.getParent();
                        if (parent != null) {
                            parent.remove(panel);
                            parent.revalidate();
                            parent.repaint();
                        }
                        ((JComponent) component).add(panel);
                        success = true;
                        dtde.acceptDrop(DnDConstants.ACTION_MOVE);
                        ((JComponent) component).invalidate();
                        ((JComponent) component).repaint();
                    } else {
                        success = false;
                        dtde.rejectDrop();
                    }
                } else {
                    success = false;
                    dtde.rejectDrop();
                }
            } catch (Exception exp) {
                success = false;
                dtde.rejectDrop();
                exp.printStackTrace();
            }
        } else {
            success = false;
            dtde.rejectDrop();
        }
        dtde.dropComplete(success);
    }
    

    It’s important to note that these above modifications probably aren’t required, but they existed after the point I got the operations to work again…

    Another issue I came across was a bunch of NotSerializableExceptions

    I was required to update the DragGestureHandler and DropHandler classes…

    public class DragGestureHandler implements DragGestureListener, DragSourceListener, Serializable {
        //...
    }
    
    public public class DropHandler implements DropTargetListener, Serializable {
        //...
    }
    

    Runnable example…

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.GridLayout;
    import java.io.Serializable;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class Test implements Serializable {
    
        public static void main(String[] args) {
            new Test();;
        }
    
        public Test() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            public TestPane() {
                setLayout(new GridLayout(1, 2));
    
                JPanel container = new OutterPane();
    
                DragPane drag = new DragPane();
                container.add(drag);
    
                add(container);
                add(new DropPane());
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
    
        }
    
        public class OutterPane extends JPanel {
    
            public OutterPane() {
                setBackground(Color.GREEN);
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(100, 100);
            }
    
        }
    
    }
    

    DragPane

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.dnd.DnDConstants;
    import java.awt.dnd.DragGestureRecognizer;
    import java.awt.dnd.DragSource;
    import javax.swing.JPanel;
    
    public class DragPane extends JPanel {
    
        private DragGestureRecognizer dgr;
        private DragGestureHandler dragGestureHandler;
    
        public DragPane() {
            System.out.println("DragPane = " + this.hashCode());
            setBackground(Color.RED);
            dragGestureHandler = new DragGestureHandler(this);
            dgr = DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_MOVE, dragGestureHandler);
        }
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(50, 50);
        }
    
    }
    

    DropPane

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.dnd.DnDConstants;
    import java.awt.dnd.DropTarget;
    import javax.swing.JPanel;
    
    public class DropPane extends JPanel {
    
        DropTarget dropTarget;
        DropHandler dropHandler;
    
        public DropPane() {
            setBackground(Color.BLUE);
        }
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(100, 100);
        }
    
        @Override
        public void addNotify() {
            super.addNotify(); //To change body of generated methods, choose Tools | Templates.
            dropHandler = new DropHandler();
            dropTarget = new DropTarget(this, DnDConstants.ACTION_MOVE, dropHandler, true);
        }
    
        @Override
        public void removeNotify() {
            super.removeNotify(); //To change body of generated methods, choose Tools | Templates.
            dropTarget.removeDropTargetListener(dropHandler);
        }
    
    }
    

    The DragGestureHandler, DropHandler, PanelDataFlavor and PanelTransferable classes remain the same, except for the changes I’ve mentioned above. All these classes are standalone, external classes, otherwise it causes additional NotSerializableException problems

    Notes

    It’s possible that having the DragGestureHandler managed by the same component which is been dragged could be causing the over all issues, but I don’t have the time to investigate

    It should be noted that, I don’t prompt nor condone manipulating components in this way, as it’s way to easy to end up in situations where a solution might work today, but won’t work tomorrow. I prefer to transfer state or data instead – much more stable.

    I had tried a dozen other examples based around the same concept presented in the original answer which simply transferred state and they all worked without issue, it was only when trying to transfer Components it failed – until the above fix was applied

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have question about python and sqlite3. I want to drop a table from
I have question about XSLT1.0. The task is to write out in HTML all
I have question about integrate Open office with PHP. I want make mail merge
I saw a lot of examples of CopyStream implementation but I have question about
I have question about how I can save the result of function I have
I'm learning asp.net. I have question about example buttons I can use two types
Have a question about linux bash. I want to start a program and then
i have question about finding maximum x or y-value in text file. This is
This question is all over SO, but no one seems to have had the
I have question about parsing in Html helper : I have sth like: @foreach

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.