JTree not updating after
To: comp.lang.java.gui
My first attempt at implementing drag and drop in Swing has been painful to
say the least. I am trying to setup DnD in a JTree and the first thing I am
attempting is to simply delete the node that is being moved from its parent.
Sounds simple? Well I can't get it to do even that.
The SSCCE attached below shows what I am talking about. I have a method
removeChildNode() which deletes the child node from the parent and notifies
the tree and I know it works because if you run the program the first time
and click on the button then node C is deleted and the tree updates.
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 C
on to B for example nothing happens. C should be deleted.
From debug it appears that the model is updating correctly but the tree
itself is not. Can anyone suggest why this might be? Lines 95-98 in the
importData() method seem to be the key but you'll see that the debug there
prints out the correct node data.
Any help much appreciated.
--
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();
DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
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) {
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;
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);
}
public void removeChildNode(DefaultMutableTreeNode parent,
DefaultMutableTreeNode child) {
final int[] childIndices = {parent.getIndex(child)};
final Object[] removedChildren = {child};
parent.remove(child);
DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
model.nodesWereRemoved(parent, 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());
tree = new JTree(root);
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) {
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);
}
});
}
}
---
* Synchronet * The Whitehouse BBS --- whitehouse.hulds.com --- check it out free usenet!
--- Synchronet 3.15a-Win32 NewsLink 1.92
Time Warp of the Future BBS - telnet://time.synchro.net:24