Stealing the contents of another application's tree view
I have an application with a very large TreeView control in Java. I want to get the contents of the tree control in a list (just strings not a JList) of XPath-like elements of leaves only. Here's an example root
|-Item1 |-Item1.1 |-Item1.1.1 (leaf) |-Item1.2 (leaf) |-Item2 |-Item2.1 (leaf)
Would output:
/Item1/Item1.1/Item1.1.1 /Item1/Item1.2 /Item2/Item2.1
I don't have any source code or anything handy like that. Is there I tool I 开发者_运维百科can use to dig into the Window item itself and pull out this data? I don't mind if there are a few post-processing steps because typing it in by hand is my only other option.
If we assume that you have a TreeModel
(which you can get from a JTree
using JTree.getModel()
), then the following code would print out the leaves of the tree in the "/"-separated format that you are looking for:
/**
* Prints the path to each leaf in the given tree to the console as a
* "/"-separated string.
*
* @param tree
* the tree to print
*/
private void printTreeLeaves(TreeModel tree) {
printTreeLeavesRecursive(tree, tree.getRoot(), new LinkedList<Object>());
}
/**
* Prints the path to each leaf in the given subtree of the given tree to
* the console as a "/"-separated string.
*
* @param tree
* the tree that is being printed
* @param node
* the root of the subtree to print
* @param path
* the path to the given node
*/
private void printTreeLeavesRecursive(TreeModel tree,
Object node,
List<Object> path) {
if (tree.getChildCount(node) == 0) {
for (final Object pathEntry : path) {
System.out.print("/");
System.out.print(pathEntry);
}
System.out.print("/");
System.out.println(node);
}
else {
for (int i = 0; i < tree.getChildCount(node); i++) {
final List<Object> nodePath = new LinkedList<Object>(path);
nodePath.add(node);
printTreeLeavesRecursive(tree,
tree.getChild(node, i),
nodePath);
}
}
}
Of course, if you didn't just want to print the tree's contents to the console, you could replace the println
statements with something else, such as output to a file or such as writing or appending to a Writer
or a StringBuilder
that is passed to these methods as an additional argument.
(I'm posting a second answer, depending on the interpretation of the question...)
If you already know what to do once you have a JTree
and you're just trying to find the JTree
component in an arbitrary Container
(including any JComponent
, Window
, JFrame
, etc.), then the following code will search the given Container
and return the first JTree
it finds (or null
if no JTree
can be found):
/**
* Searches the component hierarchy of the given container and returns the
* first {@link javax.swing.JTree} that it finds.
*
* @param toSearch
* the container to search
* @return the first tree found under the given container, or <code>null</code>
* if no {@link javax.swing.JTree} could be found
*/
private JTree findTreeInContainer(Container toSearch) {
if (toSearch instanceof JTree) {
return (JTree)toSearch;
}
else {
for (final Component child : toSearch.getComponents()) {
if (child instanceof Container) {
JTree result = findTreeInContainer((Container)child);
if (result != null) {
return result;
}
}
}
return null;
}
}
精彩评论