2

Recently I solved a "mysterious" IOException that I got while DnD items from a JList to the JTable objects. Apparently objects that I transfer must be serializable. Is this "a must", or there is a way to avoid serialization?

One thing I must note - the type I am transferring is in a different package.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
DejanLekic
  • 18,787
  • 4
  • 46
  • 77

1 Answers1

5

You can write a custom TransferHandler. For example I believe a TranferHandler for a JTabel will export a String that is comma delimited and then the import will parse the string to add each token as a different column.

So in your case you could export you data the same way. Then on you import you would need to be able to recreate your custom Object using the parsed tokens.

Take a look at the Swing tutorial on Drag and Drop and Data Transfer for more information and examples.

Or maybe easier if the DnD is only between your Java application than you can pass the actual reference to the object. Here is an example of my attempt to do something like this by dragging a Swing component between panels:

import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.*;
import javax.swing.text.*;
import java.io.*;

public class DragComponent extends JPanel
{
//  public final static DataFlavor COMPONENT_FLAVOR = new DataFlavor(Component[].class, "Component Array");
    public static DataFlavor COMPONENT_FLAVOR;

    public DragComponent()
    {
        try
        {
            COMPONENT_FLAVOR = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=\"" + Component[].class.getName() + "\"");
        }
        catch(Exception e)
        {
            System.out.println(e);
        }

        setLayout(null);
        setTransferHandler( new PanelHandler() );

        MouseListener listener = new MouseAdapter()
        {
            @Override
            public void mousePressed(MouseEvent e)
            {
                JComponent c = (JComponent) e.getSource();
                TransferHandler handler = c.getTransferHandler();
                handler.exportAsDrag(c, e, TransferHandler.MOVE);
            }
        };

        TransferHandler handler = new ComponentHandler();

        for (int i = 0; i < 5; i++)
        {
            JLabel label = new JLabel("Label " + i);
            label.setSize( label.getPreferredSize() );
            label.setLocation(30 * (i+1), 30 * (i+1));
            label.addMouseListener( listener );
            label.setTransferHandler( handler );
            add( label );
        }
    }

    private static void createAndShowUI()
    {
        DragComponent north = new DragComponent();
        north.setBackground(Color.RED);
        north.setPreferredSize( new Dimension(200, 200) );

        DragComponent south = new DragComponent();
        south.setBackground(Color.YELLOW);
        south.setPreferredSize( new Dimension(200, 200) );

        JFrame frame = new JFrame("DragComponent");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(north, BorderLayout.NORTH);
        frame.add(south, BorderLayout.SOUTH);
        frame.pack();
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}

class ComponentHandler extends TransferHandler
{
    @Override
    public int getSourceActions(JComponent c)
    {
        return MOVE;
    }

    @Override
    public Transferable createTransferable(final JComponent c)
    {
        return new Transferable()
        {
            @Override
            public Object getTransferData(DataFlavor flavor)
            {
                Component[] components = new Component[1];
                components[0] = c;
                return components;
            }

            @Override
            public DataFlavor[] getTransferDataFlavors()
            {
                DataFlavor[] flavors = new DataFlavor[1];
                flavors[0] = DragComponent.COMPONENT_FLAVOR;
                return flavors;
            }

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

    @Override
    public void exportDone(JComponent c, Transferable t, int action)
    {
        System.out.println(c.getBounds());
    }
}

class PanelHandler extends TransferHandler
{
    @Override
    public boolean canImport(TransferSupport support)
    {
        if (!support.isDrop())
        {
            return false;
        }

        boolean canImport = support.isDataFlavorSupported(DragComponent.COMPONENT_FLAVOR);
        return canImport;
    }

    @Override
    public boolean importData(TransferSupport support)
    {
        if (!canImport(support))
        {
            return false;
        }

        Component[] components;

        try
        {
            components = (Component[])support.getTransferable().getTransferData(DragComponent.COMPONENT_FLAVOR);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return false;
        }

        Component component = components[0];
        Container container = (Container)support.getComponent();
        container.add(component);
//      container.revalidate();
//      container.repaint();
        container.getParent().revalidate();
        container.getParent().repaint();

        JLabel label = (JLabel)component;
        DropLocation location = support.getDropLocation();
        System.out.println(label.getText() + " + " + location.getDropPoint());
        label.setLocation( location.getDropPoint() );
        return true;
    }
}
camickr
  • 321,443
  • 19
  • 166
  • 288
  • I believe the trick is in the `DataFlavor.javaJVMLocalObjectMimeType` you mentioned. +1 for now, i will check later if it makes java not serialize... If it does not, I will gladly accept the answer. Thank you! PS. in my case I drag/drop objects of type that inherit a common type I call "SimpleObject" (think of it as some form of Value Object). – DejanLekic Oct 24 '13 at 17:19