i want to build a tree in java. operations such as insert delete update. how to go about it? I dont want a binary tree, i want to add children based on user input
i have implemented the following
import java.util.ArrayList;
public class Tree {
private Node root;
public Tree(String rootData)
{
root=new Node();
root.data=rootData;
root.children=new ArrayList<Node>();
}
public void addChild(String name)
{
}
}
import java.util.*;
class Node {
String data;
Node parent;
List<Node> children;
public Node()
{
data=null;
children=null;
parent=null;
}
public Node(String name)
{
Node n=new Node(name);
n.data=name;
n.children=new ArrayList<Node>();
}
}
Not entirely sure what you want. You might want to look into the DefaultTreeModel implementation or the TreeModel interface for the JTree, perhaps. No need to reinvent the wheel. More often than not the wheel will look distinctly triangular.
Anyway, this might help a bit:
import java.util.ArrayList;
public class Tree {
private Node root;
public Tree(String rootData)
{
root=new Node();
root.data=rootData;
root.children=new ArrayList<Node>();
}
public List<Node> getPathToNode(Node node) {
Node currentNode = node;
List<Node> reversePath = new ArrayList<Node>();
reversePath.add(node);
while (!(this.root.equals(currentNode)) {
currentNode = currentNode.getParentNode();
reversePath.add(currentNode);
}
Collections.reverse(reversePath); // now the list is root -> node
return reversePath;
}
}
import java.util.*;
class Node {
String data;
Node parent;
List<Node> children;
/* I would remove this constructor or at least initialize the field to non-null defaults. This is bloody dangerous. */
public Node()
{
data=null;
children=null;
parent=null;
}
public Node(String name)
{
Node n=new Node(name);
n.data=name;
n.children=new ArrayList<Node>();
}
public void addChild(String name) {
this.addChild(new Node(name));
}
public void addChild(Node child) {
this.children.add(child);
}
public void removeChild(Node child) {
this.children.remove(child);
}
public void removeChild(String name) {
this.removeChild(this.getChild(name));
}
public Node getChild(int childIndex) {
return this.children.get(childIndex);
}
public Node getChild(String childName) {
for (Node child : this.children) {
if (child.getName().equals(childName)) { return child; }
}
return null;
}
public Node getParentNode() {
return this.parent;
}
}
Here is the solution
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
public class MyTree extends JFrame{
private JTree tree;
private DefaultTreeModel model;
private DefaultMutableTreeNode rootNode;
public MyTree()
{
DefaultMutableTreeNode philosophersNode = getTree();
model = new DefaultTreeModel(philosophersNode);
tree = new JTree(model);
JButton addButton = new JButton("Add ");
addButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
addNode();
}
});
JButton removeButton = new JButton("Delete");
removeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
removeSelectedNode();
}
});
JPanel inputPanel = new JPanel();
inputPanel.add(addButton);
inputPanel.add(removeButton);
Container container = getContentPane();
container.add(new JScrollPane(tree), BorderLayout.CENTER);
container.add(inputPanel, BorderLayout.NORTH);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(400, 500);
setVisible(true);
}
private DefaultMutableTreeNode getSelectedNode() {
return (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
}
private DefaultMutableTreeNode getTree() {
rootNode = new DefaultMutableTreeNode("Root");
return rootNode;
}
private void removeSelectedNode() {
DefaultMutableTreeNode selectedNode = getSelectedNode();
if (selectedNode != null){
if(selectedNode.toString()=="Root")
{
JOptionPane.showMessageDialog(MyTree.this, "Cannot delete root element", "Error",
JOptionPane.ERROR_MESSAGE);
}else{
model.removeNodeFromParent(selectedNode);
}
}
}
private void addNode() {
DefaultMutableTreeNode parent = getSelectedNode();
if (parent == null) {
JOptionPane.showMessageDialog(MyTree.this, "Select an area.", "Error",
JOptionPane.ERROR_MESSAGE);
return;
}
String name = JOptionPane.showInputDialog(MyTree.this, "Enter Name:");
model.insertNodeInto(new DefaultMutableTreeNode(name), parent, parent.getChildCount());
}
public static void main(String args[]) {
new MyTree();
}
}
Related
I have been using JTree to get the multiple root directories of the system, using the example FileTreeModel.java to achieve it. And also trying to get the selected leaf (path) but it throws cast error, please give me some directions on this, have posted the code so far have tried. Thanks.
import java.io.File;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import java.io.File;
public class FileTreeDemo {
public static void main(String[] args) {
// Figure out where in the filesystem to start displaying
File root;
if (args.length > 0) {
root = new File(args[0]);
//System.out.println(args.length);
}
else root = new File(System.getProperty("user.home"));
//System.out.println(args.length);
// Create a TreeModel object to represent our tree of files
FileTreeModel model = new FileTreeModel(root);
// Create a JTree and tell it to display our model
JTree tree = new JTree();
tree.setModel(model);
tree.setRootVisible(true);
tree.setShowsRootHandles(true);
//tree.setShowsRootHandles(true);
// The JTree can get big, so allow it to scroll.
JScrollPane scrollpane = new JScrollPane(tree);
// Display it all in a window and make the window appear
JFrame frame = new JFrame("FileTreeDemo");
frame.getContentPane().add(scrollpane, "Center");
frame.setSize(400,600);
frame.setVisible(true);
// Add a listener
tree.addTreeSelectionListener(new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) e
.getPath().getLastPathComponent();
System.out.println("You selected " + node);
}
});
}
}
class FileTreeModel implements TreeModel {
protected File root;
public FileTreeModel(File root) { this.root = root; }
public Object getRoot() { return root; }
public boolean isLeaf(Object node) { return ((File)node).isFile(); }
public int getChildCount(Object parent) {
String[] children = ((File)parent).list();
if (children == null) return 0;
return children.length;
}
public Object getChild(Object parent, int index) {
String[] children = ((File)parent).list();
if ((children == null) || (index >= children.length)) return null;
return new File((File) parent, children[index]);
}
public int getIndexOfChild(Object parent, Object child) {
String[] children = ((File)parent).list();
if (children == null) return -1;
String childname = ((File)child).getName();
for(int i = 0; i < children.length; i++) {
if (childname.equals(children[i])) return i;
}
return -1;
}
public void valueForPathChanged(TreePath path, Object newvalue) {}
public void addTreeModelListener(TreeModelListener l) {}
public void removeTreeModelListener(TreeModelListener l) {}
}
In your model you store File's instead of DefaultMutableTreeNode, because of you get ClassCastException here:
DefaultMutableTreeNode node = (DefaultMutableTreeNode)e.getPath().getLastPathComponent();
Change your listener like next:
tree.addTreeSelectionListener(new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {
File node = (File) e.getPath().getLastPathComponent();
System.out.println("You selected " + node);
}
});
I am comfortable with Java but to swing API. After googling for sometime, I have got below program working fine so far. Now what I want is, on double clicking on any file in the tree, below function to be executed.
Can someone suggest me how can I add a listener to understand double click event? Example would really help.
public boolean getSomeData(String fileName){
//I will make JDBC call here
}
My working program is as below,
/*http://www.chka.de/swing/tree/FileTreeModel.html
*/
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.swing.event.TreeModelListener;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.EventListenerList;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.io.File;
import java.io.Serializable;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
public class FileTreeModel
implements TreeModel, Serializable, Cloneable
{
protected EventListenerList listeners;
private static final Object LEAF = new Serializable() { };
private Map map;
private File root;
public FileTreeModel(File root)
{
this.root = root;
if (!root.isDirectory())
map.put(root, LEAF);
this.listeners = new EventListenerList();
this.map = new HashMap();
}
public Object getRoot()
{
return root;
}
public boolean isLeaf(Object node)
{
return map.get(node) == LEAF;
}
public int getChildCount(Object node)
{
List children = children(node);
if (children == null)
return 0;
return children.size();
}
public Object getChild(Object parent, int index)
{
return children(parent).get(index);
}
public int getIndexOfChild(Object parent, Object child)
{
return children(parent).indexOf(child);
}
protected List children(Object node)
{
File f = (File)node;
Object value = map.get(f);
if (value == LEAF)
return null;
List children = (List)value;
if (children == null)
{
File[] c = f.listFiles();
if (c != null)
{
children = new ArrayList(c.length);
for (int len = c.length, i = 0; i < len; i++)
{
children.add(c[i]);
if (!c[i].isDirectory())
map.put(c[i], LEAF);
}
}
else
children = new ArrayList(0);
map.put(f, children);
}
return children;
}
public void valueForPathChanged(TreePath path, Object value)
{
}
public void addTreeModelListener(TreeModelListener l)
{
listeners.add(TreeModelListener.class, l);
}
public void removeTreeModelListener(TreeModelListener l)
{
listeners.remove(TreeModelListener.class, l);
}
public Object clone()
{
try
{
FileTreeModel clone = (FileTreeModel)super.clone();
clone.listeners = new EventListenerList();
clone.map = new HashMap(map);
return clone;
}
catch (CloneNotSupportedException e)
{
throw new InternalError();
}
}
public static void main(String[] args)
{
if (args.length != 1)
{
System.err.println("Usage: java FileTreeModel path");
System.exit(1);
}
File root = new File(args[0]);
if (!root.exists())
{
System.err.println(root+ ": No such file or directory");
System.exit(2);
}
JTree tree = new JTree(new FileTreeModel(root));
JFrame f = new JFrame(root.toString());
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
f.getContentPane().add(new JScrollPane(tree));
f.pack();
f.setVisible(true);
}
}
I think you should add MouseListener and implement the mousePressed method
MouseListener ml = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if(e.getClickCount() == 2) {
getSomeData(...);
}
}
};
tree.addMouseListener(ml);
I have a custom JTree and a custom JModel; I would for the JTree to "auto-expand" when I give it a new model. At the moment, it simply collapse all the nodes to the root.
Here is an example:
private class CustomTree extends JTree {
#Override
public boolean isExpanded(TreePath path) {
return ((Person) path.getLastPathComponent).hasChildren();
}
private class CustomTreeModel extends TreeModel {
// ... omitting various implementation details
#Override
public boolean isLeaf(Object object) {
return !((Person) object).hasChildren();
}
}
Model model = new Model();
Person bob = new Person();
Person alice = new Person();
bob.addChild(alice);
model.setRoot(bob);
JTree tree = new CustomTree(new CustomTreeModel(model));
At this point, the tree correctly displays:
- BOB
- ALICE
where Alice is a child of Bob (both in the data and in the visual tree)
However, if I call:
tree.setModel(new CustomTreeModel(model));
everything is collapsed:
+ BOB
Is there a way to "auto-expand" everything in the tree when setting a new model?
The following worked for me (called after setting the new model):
for (int i = 0; i < tree.getRowCount(); i++) {
tree.expandRow(i);
}
I had a similar problem.
Your solution (as posted https://stackoverflow.com/a/15211697/837530) seemed to work for me only for the top level tree nodes.
But I needed to expand all the a descendants node. So I solved it with the following recursive method:
private void expandAllNodes(JTree tree, int startingIndex, int rowCount){
for(int i=startingIndex;i<rowCount;++i){
tree.expandRow(i);
}
if(tree.getRowCount()!=rowCount){
expandAllNodes(tree, rowCount, tree.getRowCount());
}
}
which is invoked with
expandAllNodes(tree, 0, tree.getRowCount());
where, tree is a JTree.
Unless someone has a better solution.
There's also this non-recursive version.
private void expandAllNodes(JTree tree) {
int j = tree.getRowCount();
int i = 0;
while(i < j) {
tree.expandRow(i);
i += 1;
j = tree.getRowCount();
}
}
this worked for me..
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeNode;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.Enumeration;
public class JTreeNodeAutoExpandCollapse extends JFrame {
public JTreeNodeAutoExpandCollapse() throws HeadlessException {
initializeUI();
}
private void initializeUI() {
setSize(200, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
DefaultMutableTreeNode chapter1 = new DefaultMutableTreeNode("Chapter 1");
DefaultMutableTreeNode sub1 = new DefaultMutableTreeNode("1.1");
DefaultMutableTreeNode sub2 = new DefaultMutableTreeNode("1.2");
DefaultMutableTreeNode sub3 = new DefaultMutableTreeNode("1.3");
DefaultMutableTreeNode sub31 = new DefaultMutableTreeNode("1.3.1");
DefaultMutableTreeNode sub32 = new DefaultMutableTreeNode("1.3.2");
root.add(chapter1);
chapter1.add(sub1);
chapter1.add(sub2);
chapter1.add(sub3);
sub3.add(sub31);
sub3.add(sub32);
final JTree tree = new JTree(root);
expandTree(tree, false);
JScrollPane pane = new JScrollPane(tree);
pane.setPreferredSize(new Dimension(200, 200));
JPanel buttonPanel = new JPanel(new BorderLayout());
JButton expandAll = new JButton("Expand All");
expandAll.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
expandTree(tree, true);
}
});
JButton collapseAll = new JButton("Collapse All");
collapseAll.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
expandTree(tree, false);
}
});
buttonPanel.add(expandAll, BorderLayout.WEST);
buttonPanel.add(collapseAll, BorderLayout.EAST);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(pane, BorderLayout.CENTER);
getContentPane().add(buttonPanel, BorderLayout.SOUTH);
}
private void expandTree(JTree tree, boolean expand) {
TreeNode root = (TreeNode) tree.getModel().getRoot();
expandAll(tree, new TreePath(root), expand);
}
private void expandAll(JTree tree, TreePath path, boolean expand) {
TreeNode node = (TreeNode) path.getLastPathComponent();
if (node.getChildCount() >= 0) {
Enumeration enumeration = node.children();
while (enumeration.hasMoreElements()) {
TreeNode n = (TreeNode) enumeration.nextElement();
TreePath p = path.pathByAddingChild(n);
expandAll(tree, p, expand);
}
}
if (expand) {
tree.expandPath(path);
} else {
tree.collapsePath(path);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new JTreeNodeAutoExpandCollapse().setVisible(true);
}
});
}
}
public void expandTree(){
int row = 1;
while (row++ < tree.getRowCount()){
tree.expandRow(row);
}
public void collapseTree(){
int row = tree.getRowCount() - 1;
while (row-- > 0){
tree.collapseRow(row);
}
}
I have a class structure as follows:
DefaultMutableTreeNode
|_
BCStructure
|_
| Module
|_
| Section
|_
Page
Module, Section, and Page are what I actually use in my JTree. If you run the sample code below, the drag and drop works. Notice it is using DefaultMutableTreeNodes. If however, I place the code in my real applicaiont which uses the subclasses of DefualtMutableTreeNode, it does not work.
While stepping through the code, I have noticed two areas of interest. The first is this:
class TreeTransferHandler extends TransferHandler {
DataFlavor nodesFlavor;
DataFlavor[] flavors = new DataFlavor[1];
DefaultMutableTreeNode[] nodesToRemove;
public TreeTransferHandler() {
try {
String mimeType = DataFlavor.javaJVMLocalObjectMimeType
+ ";class=\""
+ javax.swing.tree.DefaultMutableTreeNode[].class.getName()
+ "\"";
nodesFlavor = new DataFlavor(mimeType);
flavors[0] = nodesFlavor;
} catch (ClassNotFoundException e) {
System.out.println("ClassNotFound: " + e.getMessage());
}
}
This is where it sets the DataFlavor. It is setting it to a DefualtMutableTreeNode array which I assume is correct since DefaultMutableTreeNode is the super class of my nodes. But this was one area where I thought the problem could lie.
The other point is while debugging this code, I get as far as:
public DataFlavor[] getTransferDataFlavors() {
return flavors;
}
before the drag and drop fails. I assume that it returns a DataFlavor that is not liked to well. This is why I think there is something wrong with the DataFlavor. Is there something more I need to do/modify in order for this to work with subclasses? Any ideas or suggestions?
Thanks!
Complete sample code:
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.tree.*;
public class TreeDragAndDrop {
private JScrollPane getContent() {
JTree tree = new JTree();
tree.setDragEnabled(true);
tree.setDropMode(DropMode.ON_OR_INSERT);
tree.setTransferHandler(new TreeTransferHandler());
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.CONTIGUOUS_TREE_SELECTION);
expandTree(tree);
return new JScrollPane(tree);
}
private void expandTree(JTree tree) {
DefaultMutableTreeNode root =
(DefaultMutableTreeNode)tree.getModel().getRoot();
Enumeration e = root.breadthFirstEnumeration();
while(e.hasMoreElements()) {
DefaultMutableTreeNode node =
(DefaultMutableTreeNode)e.nextElement();
if(node.isLeaf()) continue;
int row = tree.getRowForPath(new TreePath(node.getPath()));
tree.expandRow(row);
}
}
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new TreeDragAndDrop().getContent());
f.setSize(400,400);
f.setLocation(200,200);
f.setVisible(true);
}
}
class TreeTransferHandler extends TransferHandler {
DataFlavor nodesFlavor;
DataFlavor[] flavors = new DataFlavor[1];
DefaultMutableTreeNode[] nodesToRemove;
public TreeTransferHandler() {
try {
String mimeType = DataFlavor.javaJVMLocalObjectMimeType +
";class=\"" +
javax.swing.tree.DefaultMutableTreeNode[].class.getName() +
"\"";
nodesFlavor = new DataFlavor(mimeType);
flavors[0] = nodesFlavor;
} catch(ClassNotFoundException e) {
System.out.println("ClassNotFound: " + e.getMessage());
}
}
public boolean canImport(TransferHandler.TransferSupport support) {
if(!support.isDrop()) {
return false;
}
support.setShowDropLocation(true);
if(!support.isDataFlavorSupported(nodesFlavor)) {
return false;
}
// Do not allow a drop on the drag source selections.
JTree.DropLocation dl =
(JTree.DropLocation)support.getDropLocation();
JTree tree = (JTree)support.getComponent();
int dropRow = tree.getRowForPath(dl.getPath());
int[] selRows = tree.getSelectionRows();
for(int i = 0; i 0 &&
target.getLevel() 0 && selRows.length == 1)
return false;
// first may have children.
for(int i = 1; i selRows.length-1) {
// Not all children of first are selected.
return false;
}
}
}
return true;
}
protected Transferable createTransferable(JComponent c) {
JTree tree = (JTree)c;
TreePath[] paths = tree.getSelectionPaths();
if(paths != null) {
// Make up a node array of copies for transfer and
// another for/of the nodes that will be removed in
// exportDone after a successful drop.
List copies =
new ArrayList();
List toRemove =
new ArrayList();
DefaultMutableTreeNode node =
(DefaultMutableTreeNode)paths[0].getLastPathComponent();
DefaultMutableTreeNode copy = copy(node);
copies.add(copy);
toRemove.add(node);
for(int i = 1; i node.getLevel()) { // child node
copy.add(copy(next));
// node already contains child
} else { // sibling
copies.add(copy(next));
toRemove.add(next);
}
}
DefaultMutableTreeNode[] nodes =
copies.toArray(new DefaultMutableTreeNode[copies.size()]);
nodesToRemove =
toRemove.toArray(new DefaultMutableTreeNode[toRemove.size()]);
return new NodesTransferable(nodes);
}
return null;
}
/** Defensive copy used in createTransferable. */
private DefaultMutableTreeNode copy(TreeNode node) {
return new DefaultMutableTreeNode(node);
}
protected void exportDone(JComponent source, Transferable data, int action) {
if((action & MOVE) == MOVE) {
JTree tree = (JTree)source;
DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
// Remove nodes saved in nodesToRemove in createTransferable.
for(int i = 0; i
If you think the problem is that you subclass the DefaultMutableTreeNode, try making your DataFlavor to be an array of Object, or even better, an ArrayList:
DataFlavor.javaJVMLocalObjectMimeType + ";class=java.util.ArrayList"
This way you can return your copies list along with your transferable. Maybe it will avoid the problem.
here's a rough scetch of how to do this with lists:
import javax.swing.*;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.*;
import java.util.List;
/**
* Author: Denis Tulskiy
* Date: 1/5/11
*/
public class Test extends JFrame {
class NodeA extends DefaultMutableTreeNode {
NodeA(Object userObject) {
super(userObject);
}
}
class NodeB extends DefaultMutableTreeNode {
NodeB(Object userObject) {
super(userObject);
}
}
class NodeC extends DefaultMutableTreeNode {
NodeC(Object userObject) {
super(userObject);
}
}
private static class MyTransferHandler extends TransferHandler {
#Override
public int getSourceActions(JComponent c) {
return MOVE;
}
#Override
protected Transferable createTransferable(JComponent c) {
JTree tree = (JTree) c;
ArrayList<TreeNode> nodes = new ArrayList<TreeNode>();
for (TreePath path : tree.getSelectionPaths()) {
DefaultMutableTreeNode component = (DefaultMutableTreeNode) path.getLastPathComponent();
nodes.add(component);
}
return new NodesTransferable(nodes);
}
#Override
public boolean canImport(TransferSupport support) {
return support.isDataFlavorSupported(NodesTransferable.getDataFlavor());
}
#Override
public boolean importData(TransferSupport support) {
if (!canImport(support)) {
return false;
}
JTree tree = (JTree) support.getComponent();
List<DefaultMutableTreeNode> data = null;
try {
data = (List<DefaultMutableTreeNode>) support.getTransferable().getTransferData(NodesTransferable.getDataFlavor());
} catch (UnsupportedFlavorException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (data != null) {
Point dropPoint = support.getDropLocation().getDropPoint();
TreePath path = tree.getPathForLocation(dropPoint.x, dropPoint.y);
DefaultMutableTreeNode parent = (DefaultMutableTreeNode) path.getLastPathComponent();
for (DefaultMutableTreeNode node : data) {
node.removeFromParent();
parent.add(node);
}
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
model.reload();
}
return true;
}
}
static class NodesTransferable implements Transferable {
private static DataFlavor dataFlavor;
public static DataFlavor getDataFlavor() {
if (dataFlavor == null) {
try {
dataFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=java.util.ArrayList");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return dataFlavor;
}
private java.util.List<TreeNode> nodes;
NodesTransferable(List<TreeNode> nodes) {
this.nodes = nodes;
}
#Override
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[]{getDataFlavor()};
}
#Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavor.match(dataFlavor);
}
#Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
return nodes;
}
}
public Test() {
JTree tree = new JTree();
tree.setDragEnabled(true);
tree.setDropMode(DropMode.ON_OR_INSERT);
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
NodeA child = new NodeA("nodea");
root.add(child);
child.add(new NodeB("nodeb"));
child.add(new NodeC("nodec"));
tree.setModel(new DefaultTreeModel(root));
tree.setTransferHandler(new MyTransferHandler());
setLayout(new BorderLayout());
add(tree, BorderLayout.CENTER);
setSize(300, 400);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new Test().setVisible(true);
}
}
I would like to transform XML-document to java-tree-structure, but I do not know what is a java-tree-structure? For example, JTree or another? is it exists any library?
You could use an XML DOM tree expressed in Java. An XML parser will give it to you straight away.
If your XML conforms to a specific schema (and you have an XSD file for it), you can use JAXB to convert the XSD into a bunch of Java classes for conveniently manipulating the data.
You can populate a JTree with the SAXTreeBuilder construct in import org.xml.sax. Something like (NOTE: I didn't write the code below)
/*
Java, XML, and Web Services Bible
Mike Jasnowski
ISBN: 0-7645-4847-6
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.Event.*;
import java.io.*;
import javax.swing.tree.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import org.apache.xerces.parsers.*;
public class XMLTreeView {
private SAXTreeBuilder saxTree = null;
private static String file = "";
public static void main(String args[]){
JFrame frame = new JFrame("XMLTreeView: [ games.xml ]");
frame.setSize(400,400);
frame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent ev){
System.exit(0);
}
});
file = "games.xml";
new XMLTreeView(frame);
}
public XMLTreeView(JFrame frame){
frame.getContentPane().setLayout(new BorderLayout());
DefaultMutableTreeNode top = new DefaultMutableTreeNode(file);
// DefaultMutableTreeNode top = new DefaultMutableTreeNode("XML Document");
saxTree = new SAXTreeBuilder(top);
try {
SAXParser saxParser = new SAXParser();
saxParser.setContentHandler(saxTree);
saxParser.parse(new InputSource(new FileInputStream(file)));
}catch(Exception ex){
top.add(new DefaultMutableTreeNode(ex.getMessage()));
}
JTree tree = new JTree(saxTree.getTree());
JScrollPane scrollPane = new JScrollPane(tree);
frame.getContentPane().add("Center",scrollPane);
frame.setVisible(true);
}
}
class SAXTreeBuilder extends DefaultHandler{
private DefaultMutableTreeNode currentNode = null;
private DefaultMutableTreeNode previousNode = null;
private DefaultMutableTreeNode rootNode = null;
public SAXTreeBuilder(DefaultMutableTreeNode root){
rootNode = root;
}
public void startDocument(){
currentNode = rootNode;
}
public void endDocument(){
}
public void characters(char[] data,int start,int end){
String str = new String(data,start,end);
if (!str.equals("") && Character.isLetter(str.charAt(0)))
currentNode.add(new DefaultMutableTreeNode(str));
}
public void startElement(String uri,String qName,String lName,Attributes atts){
previousNode = currentNode;
currentNode = new DefaultMutableTreeNode(lName);
// Add attributes as child nodes //
attachAttributeList(currentNode,atts);
previousNode.add(currentNode);
}
public void endElement(String uri,String qName,String lName){
if (currentNode.getUserObject().equals(lName))
currentNode = (DefaultMutableTreeNode)currentNode.getParent();
}
public DefaultMutableTreeNode getTree(){
return rootNode;
}
private void attachAttributeList(DefaultMutableTreeNode node,Attributes atts){
for (int i=0;i<atts.getLength();i++){
String name = atts.getLocalName(i);
String value = atts.getValue(name);
node.add(new DefaultMutableTreeNode(name + " = " + value));
}
}
}