Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / GUI / September 2004

Tip: Looking for answers? Try searching our database.

null UserObject  after drag n drop in JTree

Thread view: 
Girish  Chavan - 29 Sep 2004 19:19 GMT
Hi Gurus,

I am implementing simple drag n drop for mutabletreenodes between
JTrees. I simply want to copy nodes from on JTree to another by
dragging them over.

Now this works fine when I am using String as userObject in the
mutabletreenode. But if I use my own complex userObject (that overrides
toString) the node gets copied over to the destination tree, but its
userObject is set to null. So there isnt any label displayed beside the
node.

I am thinkin one of 2 things :

1. some dumb stupid mistake on my part.
2. objects that are being d-n-ded must be Serializable

Here is a sample program that demos the problem.

Thanks a lot in advance.

3 files total
--------------------------------------------------------------------
DNDTreeTest.java

import java.awt.FlowLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

public class DNDTreeTest extends JFrame {

public static void main(String[] args) {

DNDTreeTest demo = new DNDTreeTest();

Object[] hierarchy =
{ "javax.swing",
"javax.swing.border",
"javax.swing.colorchooser",
"javax.swing.event",
"javax.swing.filechooser",
new Object[] { "javax.swing.plaf",
"javax.swing.plaf.basic",
"javax.swing.plaf.metal",
"javax.swing.plaf.multi" },
"javax.swing.table",
new Object[] { "javax.swing.text",
new Object[] { "javax.swing.text.html",
"javax.swing.text.html.parser"
},
"javax.swing.text.rtf" },
"javax.swing.tree",
"javax.swing.undo" };
DefaultMutableTreeNode root = demo.processHierarchy(hierarchy);

demo.setTitle("DND Tree Demo");

DragSourceJTree src = new DragSourceJTree(new
DefaultTreeModel(root));

DropTargetJTree dest = new DropTargetJTree(new
DefaultTreeModel(root));

demo.getContentPane().setLayout(new FlowLayout());

demo.getContentPane().add(src);
demo.getContentPane().add(dest);

demo.addWindowListener(new WindowAdapter(){

public void windowClosing(WindowEvent arg0) {
System.exit(0);
}
});

demo.pack();
demo.show();

}

private DefaultMutableTreeNode processHierarchy(Object[] hierarchy)
{

MyConcept c = new MyConcept();
c.setText(hierarchy[0].toString());
DefaultMutableTreeNode node =
new DefaultMutableTreeNode(c);

DefaultMutableTreeNode child;
for(int i=1; i<hierarchy.length; i++) {
Object nodeSpecifier = hierarchy[i];
if (nodeSpecifier instanceof Object[])  // Ie node with children
child = processHierarchy((Object[])nodeSpecifier);
else
{
MyConcept c1 = new MyConcept();
c1.setText(nodeSpecifier.toString());
child = new DefaultMutableTreeNode(c1); // Ie Leaf

//             child = new DefaultMutableTreeNode(nodeSpecifier); // Ie Leaf
}
node.add(child);
}
return(node);
}

public class MyConcept
{

public String toString()
{
return pt;
}

String pt;

MyConcept()
{
pt = "";
}

public void setText(String text) {
this.pt = text;
}
}

}
-------------------------------------------------------------------
DragSourceJTree.java

import java.awt.dnd.DnDConstants;
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.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

public class DragSourceJTree extends JTree implements
DragGestureListener,
DragSourceListener {

public DragSourceJTree() {
this(new DefaultTreeModel(new DefaultMutableTreeNode()));
}

/**
* @param model
*/
public DragSourceJTree(DefaultTreeModel model) {

super(model);

DragSource dragSource = DragSource.getDefaultDragSource();

//        creating the recognizer is all that's necessary - it
//        does not need to be manipulated after creation

dragSource.createDefaultDragGestureRecognizer(this, // component
where drag originates
DnDConstants.ACTION_COPY, // actions
this); // drag gesture listener
}

public void dragGestureRecognized(DragGestureEvent e) {

System.out.println("drag started");
TreePath path =
this.getPathForLocation(e.getDragOrigin().x,e.getDragOrigin().y);
DefaultMutableTreeNode node =
(DefaultMutableTreeNode)path.getLastPathComponent();

if(node.getUserObject()==null)
System.out.println("userobj null at source");
else
System.out.println("dragging " + node.getUserObject().toString());

//        e.startDrag(DragSource.DefaultCopyDrop, // cursor
//        new TransferableNode(node.getUserObject()), // transferable
//        this); // drag source listener

e.startDrag(DragSource.DefaultCopyDrop, // cursor
new TransferableNode(node), // transferable
this); // drag source listener

}

public void dragDropEnd(DragSourceDropEvent e) {}
public void dragEnter(DragSourceDragEvent e) {}
public void dragExit(DragSourceEvent e) {}
public void dragOver(DragSourceDragEvent e) {}
public void dropActionChanged(DragSourceDragEvent e) {}

}
------------------------------------------------------------------
DropTargetJTree.java

import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.IOException;

import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

public class DropTargetJTree extends JTree implements
DropTargetListener {

public DropTargetJTree() {
this(new DefaultTreeModel(new DefaultMutableTreeNode()));
}

/**
* @param model
*/
public DropTargetJTree(DefaultTreeModel model) {

super(model);
new DropTarget(this, this);
}

public void dragEnter(DropTargetDragEvent arg0) {
System.out.println("drag enter");

}

public void dragOver(DropTargetDragEvent arg0) {}

public void dropActionChanged(DropTargetDragEvent arg0) {}

public void drop(DropTargetDropEvent e) {
try {
System.out.println("dropped");
Transferable tr = e.getTransferable();

//flavor not supported, reject drop
if (!tr.isDataFlavorSupported(
TransferableNode.TREENODE_FLAVOR)) e.rejectDrop();

//cast into appropriate data type
DefaultMutableTreeNode node =
(DefaultMutableTreeNode) tr.getTransferData(
TransferableNode.TREENODE_FLAVOR );

//System.out.println(node.getChildCount());
//System.out.println(node.getUserObject().toString());

//DefaultMutableTreeNode newnode = new
DefaultMutableTreeNode();
//newnode.setUserObject(tr.getTransferData(
TransferableNode.TREENODE_FLAVOR));

DefaultMutableTreeNode newnode = new
DefaultMutableTreeNode(node);

DefaultMutableTreeNode root =
(DefaultMutableTreeNode)this.getModel().getRoot();

((DefaultTreeModel)this.getModel()).insertNodeInto(newnode,root,root.getChildCount());

root.add(newnode);

try {
e.acceptDrop (DnDConstants.ACTION_COPY);
}
catch (java.lang.IllegalStateException ils) {
e.rejectDrop();
}

e.getDropTargetContext().dropComplete(true);

}
catch (IOException io) { e.rejectDrop(); }
catch (UnsupportedFlavorException ufe) {e.rejectDrop();}
} //end of method

public void dragExit(DropTargetEvent arg0) {
System.out.println("drag exit");

}
}

========================================================================
Andrew Thompson - 29 Sep 2004 19:46 GMT
> Here is a sample program that demos the problem.

No it doesn't.  Your example is broke, it does not compile.  
Even after I split it into three files and fixed the line wrap,
the compiler complains of a missing 'Transferable' class.

For tips on preparing code that others might help you with..
<http://www.physci.org/codes/sscce.jsp>

Try again, get the total lines under 200, and I will
have another look.

Signature

Andrew Thompson
http://www.PhySci.org/codes/  Web & IT Help
http://www.PhySci.org/  Open-source software suite
http://www.1point1C.org/  Science & Technology
http://www.lensescapes.com/  Images that escape the mundane

Girish  Chavan - 29 Sep 2004 19:54 GMT
Hi Andrew,

thanks a lot for taking a look.  Yeah I missed one class there. Sorry
about that.

Anyways, I just solved the problem. It turns out, my initial hunch was
right, the objects that are being dragged n dropped need to be
Serializable. I just added a Serializable interface to my userObject
and it  worked .perfectly.

Here is the missing class, Andrew was talking about  in case anybody
wants to try out the example
--------------
TransferableNode.java

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;

import javax.swing.tree.DefaultMutableTreeNode;

public class TransferableNode implements Transferable {

Object node;

public TransferableNode(Object node) {
super();
this.node = node;
}

final public static DataFlavor TREENODE_FLAVOR =
new DataFlavor(DefaultMutableTreeNode.class, "Default Mutable Tree
Node");

static DataFlavor flavors[] = {TREENODE_FLAVOR };

public DataFlavor[] getTransferDataFlavors() {
return flavors;
}

public boolean isDataFlavorSupported(DataFlavor df) {
return(df.equals(TREENODE_FLAVOR));
}

public Object getTransferData(DataFlavor df)
throws UnsupportedFlavorException, IOException {

if(df.equals(TREENODE_FLAVOR))
{
//System.out.println("userobj while sending to droptarget:" +
((DefaultMutableTreeNode)node).getUserObject().toString());
return node;
}
else
throw new UnsupportedFlavorException(df);
}

}
-----------------------------------------------------------------------------------
Andrew Thompson - 29 Sep 2004 20:13 GMT
> thanks a lot for taking a look.  

You're welcome.

>..Yeah I missed one class there. Sorry about that.

The link I gave you has some good tips though, I recommend
you read it.  Not only does it help you to check that the
example is 'ready to go', but gives tips on how to make it so.

For example, there would be no need to separate the Java
source into separate files if the classes were all declared
'default'.

> Anyways, I just solved the problem.

That's the main thing.   :-)

Signature

Andrew Thompson
http://www.PhySci.org/codes/  Web & IT Help
http://www.PhySci.org/  Open-source software suite
http://www.1point1C.org/  Science & Technology
http://www.lensescapes.com/  Images that escape the mundane



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.