participate


Swing - Drag and Drop for JPanel - Wrong getTransferable() of TransferSupport?
<<   Back to Forum  |   Give us Feedback
10 Duke Stars available
This topic has 2 replies on 1 page.
sw1679
Posts:12
Registered: 9/22/99
Drag and Drop for JPanel - Wrong getTransferable() of TransferSupport?   
Jul 29, 2009 7:43 AM

 
Hello,

I failed to implement a JPanel-Subclass-DnD in Java 6. It seems that the Method getTransferable() of a tansferSupport-Object doesn't really supply the Transferable during
canImport(TransferSupport support)
or
importData(TransferSupport support)

Please can You give me any hint?

I provided a SSCCE in the next post.

Please have a look at MyTransferHandler.canImport. The TransferSupport.getTransferable() does not what the api says.

I noticed that the System.out's produce the following:

[During dragging:]

Begin of mouseDragged(MouseEvent e)
End of mouseDragged(MouseEvent e)
canImport(TransferSupport support)
Src: null Dest: (0|0)
canImport(TransferSupport support)
Src: null Dest: (0|0)
[...]

[and when releasing the button:]

importData(TransferSupport support)
exportDone(JComponent c, Transferable tr, int action)

The exportDone() is called after canImport() ???
Who wonders, why there's no information about the Transferable-Data during canImport() or importData()

What am I doing wrong?

Thanks a lot

Thorsten

P.S.: I also tried it without the singleton for MyTransferHandler, this doesn't change anything.
 
sw1679
Posts:12
Registered: 9/22/99
SSCCE   
Jul 29, 2009 7:51 AM (reply 1 of 2)  (In reply to original post )

 
Hi,

I see - it's not as simple as it seems, so here's a complete SSCCE:

Additionally I found a workaround one could use (see the comments in the code), but this workaround doesn't affect the wrong TransferSupport.getTransferable() - Method.

I'm dealing a long time with Java and until now I was sure, I would never ever find an error in the api. Please give me a prove that my code is erroneous.

MyDragAndDrop.java
package myDragAndDrop;
 
import java.awt.Color;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
 
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.TransferHandler;
 
public class MyDragAndDrop {
 
    private static void createAndShowGUI() {
        MyTransferable[][] data = new MyTransferable[3][3];
        for (int x=0; x<3; x++) {
            for (int y=0; y<3; y++) {
                data[x][y] = new MyTransferable("("+x+"|"+y+")");
            }
        }
        MyFrame myFrame = new MyFrame(data);
        myFrame.setVisible(true);
    }
    
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
 
} // MyDragAndDrop
 
@SuppressWarnings("serial")
class MyFrame extends JFrame {
 
    public MyFrame(MyTransferable[][] data) {
        super();
        this.setSize(300, 200);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        GridLayout gridLayout = new GridLayout();
        gridLayout.setRows(3);
        gridLayout.setHgap(10);
        gridLayout.setVgap(10);
        gridLayout.setColumns(3);
        JPanel jContentPane = new JPanel();
        jContentPane.setLayout(gridLayout);
        for (int x=0; x<3; x++) {
            for (int y=0; y<3; y++) {
                jContentPane.add(new MyDnDPnl(data[x][y]));
            }
        }
        this.setContentPane(jContentPane);
    } // Constructor
 
} // MyFrame
 
class MyTransferable implements Transferable {
 
    private static DataFlavor dataFlavor;
    
    private String name;
    
    public MyTransferable(String name) {
        super();
        this.name = name;
    }
    
    public String toString() {
        return name;
    }
 
 
    static {
        try {
            dataFlavor = new DataFlavor(
                    DataFlavor.javaJVMLocalObjectMimeType +
            ";class=myDragAndDrop.MyTransferable");
        } catch (ClassNotFoundException e) {
            throw new Error(e);
        }
    }
    
    public Object getTransferData(DataFlavor df) throws UnsupportedFlavorException, IOException {
        if (!df.equals(dataFlavor)) throw new UnsupportedFlavorException(df);
        return this;
    }
    
    public DataFlavor[] getTransferDataFlavors() {
        DataFlavor[] dfA = new DataFlavor[1];
        dfA[0] = dataFlavor;
        return dfA;
    }
  
    public boolean isDataFlavorSupported(DataFlavor df) {
        return df.equals(dataFlavor);
    }
 
    public static DataFlavor getDataFlavor() {
        return dataFlavor;
    }
 
} // MyTransferable
 
@SuppressWarnings("serial")
class MyDnDPnl extends JPanel {
 
    MyTransferable data = null; 
 
    public MyDnDPnl(MyTransferable data) {
        
        this.setSize(300, 200);
        this.setLayout(new GridBagLayout());
        this.setBackground(Color.black);
 
        this.data = data;
        
        // DnD
        setTransferHandler(MyTransferHandler.getInstance()); 
 
        addMouseMotionListener(new MouseAdapter() {  
            public void mouseDragged(MouseEvent e) { 
                System.out.println("Begin of mouseDragged(MouseEvent e)");
              JComponent c = (JComponent)e.getSource(); 
              TransferHandler th = c.getTransferHandler();
              th.exportAsDrag(c, e, TransferHandler.MOVE);
              // MyTransferHandler.setSource(getData()); // Workaround
              System.out.println("End of mouseDragged(MouseEvent e)");
            } 
          });
 
        
        setName(data.toString());
    } // Constructor
 
    public MyTransferable getData() {
        return data;
    }
 
} // MyDnDPnl
 
sw1679
Posts:12
Registered: 9/22/99
SSCCE (continued)   
Jul 29, 2009 7:52 AM (reply 2 of 2)  (In reply to #1 )

 
...anybody who finds a shorter SSCCE is very welcome - here part two of "MyDragAndDrop.java"...

@SuppressWarnings("serial")
class MyTransferHandler extends TransferHandler {
 
    private static MyTransferHandler instance = new MyTransferHandler();
    
    private MyTransferHandler() {
        // Singleton
    }
 
    public  static MyTransferHandler getInstance() {
        return instance;
    }
    
    public int getSourceActions(JComponent c) {
        return MOVE;
    }
 
    protected Transferable createTransferable(JComponent c) {
        Transferable tr = ((MyDnDPnl)c).getData();
        return tr;
    }
 
    protected void exportDone(JComponent c, Transferable tr, int action) {
        super.exportDone(c, tr, action);
        System.out.println("exportDone(JComponent c, Transferable tr, int action)");
    }
 
 
    public boolean canImport(TransferSupport support) {
 
        System.out.println("canImport(TransferSupport support)");
 
        if (!support.isDataFlavorSupported(MyTransferable.getDataFlavor())) {
            System.out.println("flavor not supported");
            return false;
        }
 
        // support.getTransferable().getClass().getName() returns 
        // "java.awt.dnd.DropTargetContext$TransferableProxy"
        // The next statement would cause
        // an ClassCastException because
        // java.awt.dnd.DropTargetContext$TransferableProxy 
        // cannot be cast to myDnD.MyTransferable
        // Then this Method (canImport) would return.
        // (I couldn't believe it, too)
        
        MyTransferable src = (MyTransferable)(support.getTransferable());
 
        // MyTransferable src = null;                   
        
        // MyTransferable src = (MyTransferable)source; // Workaround
        
        // This statement isn't reached at all,
        // but the statement does, what it shall do.
        MyTransferable dest = ((MyDnDPnl)(support.getComponent())).getData();
        
        System.out.println("Src: " + src + " Dest: " + dest);
 
        return true; // resp. the test, if "src" can be imported by "dest".
    }
    
    public boolean importData(TransferSupport support) {
 
        System.out.println("importData(TransferSupport support)");
 
        // support.getTransferable().getClass().getName() returns 
        // "java.awt.dnd.DropTargetContext$TransferableProxy"
        // The next statement causes
        // an ClassCastException because
        // java.awt.dnd.DropTargetContext$TransferableProxy 
        // cannot be cast to myDnD.MyTransferable
        // Then this Method (importData) returns.
        // (I couldn't believe it, too)
        MyTransferable src = (MyTransferable)(support.getTransferable());
 
        // This statement isn't reached 
        // but the statement does, what it shall do.
        MyTransferable dest = ((MyDnDPnl)(support.getComponent())).getData();
 
        System.out.println("Src: " + src + " Dest: " + dest);
        
        
        if (canImport(support)) {
             // do the Import
             return true;
        }  else {
             return false;
        }
 
    }
    
    ////////////////////////////////////////////
    // This is a workaround: ///////////////////
    private static Transferable source = null;
    public static void setSource(Transferable src) {
        source = src;
    }
    public static Transferable getSource() {
        return source;
    }
    ////////////////////////////////////////////
    
} // MyTransferHandler
 
This topic has 2 replies on 1 page.
Back to Forum
 
Read the Developer Forums Code of Conduct

Click to email this message Email this Topic

Edit this Topic
  
 
 
Forums Statistics
    Users Online : 28
  • Guests : 129

About Sun forums
  • Oracle Forums is a large collection of user generated discussions. It is here to help you ask questions, find answers, and participate in discussions.

    Check out our guide on Getting started with Oracle Forums for a full walkthrough of how to best leverage the benefits of this community.

Powered by Jive Forums