
Signature
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
>>However, when I call the same method on the same nodes in the transfer
>>handler nothing appears to happen so if you run the program again and drag
[quoted text clipped - 9 lines]
> int[] childIndices,
> Object[] children )
1. What's the difference between nodesRemoved() which I already call and
fireTreeNodesRemoved()?
2. Why do there seem to be groups of 2 methods to do the same thing such as
those in (1) and those of the form nodesXXXX() and fireNodesXXXX()?
3. When I add either of these 2 lines to the code, A is deleted as well as C
which is still not correct:
fireTreeNodesRemoved(parent, new TreePath(root).getPath(), childIndices,
removedChildren);
fireTreeStructureChanged(parent, new TreePath(root).getPath(), childIndices,
removedChildren);
4. I have tried many combinations of the methods in (2) and none of them
gives the correct result. How do I get this to work inside the context of a
transfer handler? (Some do work from the button).
Revised code follows.

Signature
And loving it,
-Q
_________________________________________________
Qu0llSixFour@gmail.com
(Replace the "SixFour" with numbers to email me)
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.TransferHandler;
import javax.swing.WindowConstants;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
public class TreeDnDTestFrame extends JFrame {
public static final DataFlavor MY_FLAVOR = new DataFlavor(String.class,
"MyFlavor");
class MyTransferable implements Transferable {
private final DataFlavor[] flavors = {MY_FLAVOR};
private DefaultMutableTreeNode data;
public MyTransferable(final DefaultMutableTreeNode data) {
this.data = data;
}
@Override
public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException, IOException {
if (flavor.equals(flavors[0])) {
return (Object)data;
} else {
throw new UnsupportedFlavorException(flavor);
}
}
@Override
public DataFlavor[] getTransferDataFlavors() {
return (DataFlavor[])flavors.clone();
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
for (DataFlavor df : flavors) {
if (df.equals(flavor)) {
return true;
}
}
return false;
}
}
class MyTransferHandler extends TransferHandler {
@Override
protected Transferable createTransferable(JComponent c) {
JTree tree = (JTree)c;
Object o = tree.getSelectionPath().getLastPathComponent();
DefaultMutableTreeNode node = (DefaultMutableTreeNode)o;
return new MyTransferable(node);
}
@Override
public boolean importData(TransferSupport support) {
Point dropPoint = support.getDropLocation().getDropPoint();
JTree tree = (JTree)support.getComponent();
TreePath path = tree.getPathForLocation(dropPoint.x, dropPoint.y);
if (path == null) {
return false;
} else {
DefaultMutableTreeNode target =
(DefaultMutableTreeNode)path.getLastPathComponent();
DefaultMutableTreeNode data = null;
try {
data =
(DefaultMutableTreeNode)support.getTransferable().getTransferData(MY_FLAVOR);
}
catch (UnsupportedFlavorException ufe) {
return false;
}
catch (IOException ioe) {
return false;
}
DefaultMutableTreeNode parent =
(DefaultMutableTreeNode)data.getParent();
System.out.println("data = " + data + ", target = " + target + ", parent
= " + parent);
if (parent != null) {
model.removeChildNode(parent, data);
}
}
return true;
}
@Override
public boolean canImport(TransferSupport support) {
return true;
}
@Override
public int getSourceActions(JComponent c) {
return MOVE;
}
}
private DefaultMutableTreeNode root, a, b, c;
private JTree tree;
private MyTreeModel model;
public TreeDnDTestFrame() {
setupModel();
defineGUI();
}
public void setupModel() {
root = new DefaultMutableTreeNode("ROOT");
a = new DefaultMutableTreeNode("A");
root.add(a);
b = new DefaultMutableTreeNode("B");
root.add(b);
c = new DefaultMutableTreeNode("C");
a.add(c);
}
class MyTreeModel extends DefaultTreeModel {
public MyTreeModel(DefaultMutableTreeNode root) {
super(root);
}
public void removeChildNode(DefaultMutableTreeNode parent,
DefaultMutableTreeNode child) {
final int[] childIndices = {parent.getIndex(child)};
final Object[] removedChildren = {child};
parent.remove(child);
nodesWereRemoved(parent, childIndices, removedChildren);
fireTreeNodesRemoved(parent, new TreePath(root).getPath(), childIndices,
removedChildren);
}
}
public void defineGUI() {
tree = new JTree();
JScrollPane scrollPane = new JScrollPane();
JPanel panel = new JPanel();
setPreferredSize(new Dimension(800, 600));
setMinimumSize(new Dimension(800, 600));
setLayout(new BorderLayout());
model = new MyTreeModel(root);
tree = new JTree(root);
tree.setModel(model);
tree.setDragEnabled(true);
tree.setTransferHandler(new MyTransferHandler());
scrollPane = new JScrollPane(tree);
scrollPane.setBorder(BorderFactory.createEmptyBorder());
JButton b = new JButton("Delete C");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
model.removeChildNode(a, c);
}
});
panel = new JPanel();
panel.setLayout(new CardLayout(8, 8));
panel.add(scrollPane, "Tree");
add(panel, BorderLayout.CENTER);
add(b, BorderLayout.SOUTH);
pack();
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new TreeDnDTestFrame().setVisible(true);
}
});
}
}
Roedy Green - 24 Jul 2007 08:41 GMT
>1. What's the difference between nodesRemoved() which I already call and
>fireTreeNodesRemoved()?
The idea is you make a great string of changes to your model. You
DON'T repaint until you are done. Then when you are done all your
tinkering, you tell the GUI what you changed with the firexxx methods
so it can do all the repainting in one quick pass.

Signature
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com