I found some details on the internet for this problem but the solution does not seem to work.
I want to be able to expand all the nodes ( including the leaf nodes ) of a JTree. This is the code I have so far.
tree = new JTree(treeModel);
tree.setShowsRootHandles(true);
tree.setEditable(true);
tree.addTreeSelectionListener(treeSelectionListener);
tree.addMouseListener(mouselistener);
tree.setCellRenderer(new FileCellRenderer());
for (int i = 0; i < tree.getRowCount(); i++) {
tree.expandRow(i);
}
This however does not expand all the leaf nodes. What I get is IMAGE A but what I want is IMAGE B:
Use a recursive call, as in the following sample:
private void expandAllNodes(JTree tree, int startingIndex, int rowCount){
for(int i=startingIndex;i<rowCount;++i){
tree.expandRow(i);
}
if(tree.getRowCount()!=rowCount){
expandAllNodes(rowCount, tree.getRowCount());
}
}
Related
I'm working on building a partial tree for Monte Carlo Search Tree, I have my node class and it contains things like the game board, who's turn it is, and a list of Nodes for the children nodes. The node constructor takes in a game board and the depth (of the tree) as the parameters. For the root node I call it like so:
Node root = new Node(this.quartoBoard, currentDepth);
(Where depth is 0) that works fine, however, when depth 1, which will be the children of the root node needs to contain 32 nodes. I naively tried this:
for(int i = 0; i < NUMBER_OF_PIECES; i++) {
Node c1 = new Node(this.quartoBoard, currentDepth);
c1.setParent(root);
childrenList1.add(c1);
}
And realized that Nodes can not be created in a for loop like this. Is there an alternative to declaring each node one at a time like so:
Node child1 = new Node(this.quartoBoard, currentDepth);
Node child2 = new Node(this.quartoBoard, currentDepth);
I need to create over 800 nodes and I feel like there is a better way to do it, I just am drawing blanks on how. Any help is greatly appreciated!
I am using a JTree in which new nodes needs to be inserted dynamically to the root(consider adding children to root). Once the user selects a node and clicks a button, the new node needs to be added after the selected node. If none of the node is selected then it adds the new node at the end of the tree. Below is my code
public void addNodeToRoot(TestCase testCase) {
DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(testCase.toString());
int currentNoOfChildren = getTcBuilderTree().getModel().getChildCount(getTcBuilderTree().getModel().getRoot());
TreePath currentSelection = getTcBuilderTree().getSelectionPath();
int currentIndex=0;
//if the user has not selected a node add the test case at the end of the tree
if (currentSelection == null) {
currentIndex = currentNoOfChildren;
}
//if user has selected a node then insert the new node after the selected node
else {
int[] currentSelectedIndex = getTcBuilderTree().getSelectionRows();
currentIndex = currentSelectedIndex[0];
}
treeModel.insertNodeInto(childNode, getRoot(), currentIndex);
}
it works all fine but the code gives an exception when there are child nodes in the level 3 as well. The reason is when the tree has more levels and when its expanded then the currentIndex gives unexpected number (it counts all the indexes in all levels up from the root to the selected node) and the app gives ArrayIndexOutOfBoundsException since the currentIndex becomes greater than currentNoOfChildren
If the tree is not expanded then everything happens correctly. Please let me know how to resolve this. Is there any other way to get the no of children of a specific level in the tree?
Maybe code below can resolve your problem.
int currentNoOfChildren = getTcBuilderTree().getVisibleRowCount();
I know this question has been asked before in a similar way, maybe for icons.
What I'm trying is to change the color of the text of the tree node.
In fact, I have a jTree and I will want to set up three differents colors, default one, red and orange.
The purposse, is that if I compare that tree with another one, highlight differences between both trees (default means no diff, orange means just value diff and red means node is complete different)
I have two functions, one which trasverse the "original" tree looking for a node from the compared one, and returns false if {node} is not found:
private Boolean findNodeInRefTree(DefaultTreeModel model, Object root, DefaultMutableTreeNode node){
Boolean bRet = false;
for (int i = 0; ((i < model.getChildCount(root))&&(!bRet)); i++){
DefaultMutableTreeNode child = (DefaultMutableTreeNode) model.getChild(root, i);
bRet = node.getUserObject().equals(child.getUserObject());
if (!bRet)
bRet = findNodeInRefTree(model, child, node);
}//for:i
return bRet;
}
And another function that trasverse the "compare" tree and calls the above for each node.
private void compareTrees(TreeModel model, Object root){
for (int i = 0; i < model.getChildCount(root); i++){
DefaultMutableTreeNode child = (DefaultMutableTreeNode) model.getChild(root, i);
//find if node exists in original
DefaultTreeModel modelRef = (DefaultTreeModel) _ref.getModel();
if (!findNodeInRefTree(modelRef, modelRef.getRoot(), child)){
DefaultTreeCellRenderer render = (DefaultTreeCellRenderer) _temp.getCellRenderer();
render.setForeground(Color.RED);
_temp.setCellRenderer(render);
}//fi
_new.insertNodeInto((DefaultMutableTreeNode) child, (DefaultMutableTreeNode) root, i);
compareTrees(model, child);
}//for:i
}
Then, when it ends I just set the model of the new tree {_new} to the new tree {_temp}, and add the tree to its panel. But the tree doesn't has any different color. Obviously, I'm testing with different trees. Any suggestion?
If I understand your code correctly, your do the comparison at creation time and set the renderer for each tree node (i.e. multiple times) inside method compareTrees.
Unfortunately, that is not the way tree renderers are handled in swing. The renderer is prepared on request during rendering the tree component. Thus setting multiple renderer beforehand won't do anything useful.
A possible approach would be to do the comparison and save the result (i.e. color) in your tree model. You can then write a basic tree renderer which reads this value for the current node and sets the rendering color accordingly.
I have some DefaultMutableTreeNode's.
While the programm's running, I can change the text and revalidate it.
But if the text is too long, so for example the text "tested", the text will be displayed as "te...".
How do I change this ?
Thanks
you have to read tutorial about JTree, and examples how to use TreeCellRenderer
if you'll real question then please update your question and add there the code in SSCCE form
the underlying reason is that the layout of the tree nodes is cached and the cache not updated properly. Might f.i. happen if the node is changed under feet of the model, uncomment the nodeChanged to see the difference
JTree tree = new JTree();
DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel().getRoot();
int index = 0;
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
String result = "\n";
Enumeration<?> enumer = root.preorderEnumeration();
while (enumer.hasMoreElements()) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) enumer.nextElement();
String nodeValue = String.valueOf(node.getUserObject());
node.setUserObject(nodeValue + ": " + index++);
//model.nodeChanged(node);
}
The exact reason in your context might vary, no way to tell without an sscce
I have a ftp program that retrieve folder data each time expanded. It does this by using a model like this:
private void FilesTreeTreeExpanded(javax.swing.event.TreeExpansionEvent evt) {
String path = new String("");
DefaultMutableTreeNode chosen = (DefaultMutableTreeNode) evt.getPath().getLastPathComponent();
String[] pathArray = evt.getPath().toString().replaceAll("]", "").split(",");
for (int i = 1 ; i < pathArray.length ; i++) path += "/"+ pathArray[i].trim();
// i were aded chosen.removeAllChildren(); without success
ftp.GoTo(path);
ArrayList listDir = null;
listDir = ftp.ListDir();
ArrayList listFiles = null;
listFiles = ftp.ListFiles();
DefaultMutableTreeNode child = null , dir = null , X = null;
//this will add files to tree
for (int i = 0; i < listFiles.size(); i++) {
child = new DefaultMutableTreeNode(listFiles.get(i));
if(listFiles.size() > 0)
model.insertNodeInto(child, chosen, 0);
}
//this will add dirs to list
for (int i = 0; i < listDir.size(); i++) {
X = new DirBranch("در حال دریافت اطلاعات ...").node();
dir = new DirBranch( (String) listDir.get(i)).node();
dir.add(X);
if(listDir.size() > 0)
model.insertNodeInto(dir, chosen, 0);
}
FilesTree.setModel(model); //this is my Swing JTree
}
the problem is every time i expand the JTree it duplicate list of files and folders. so i tried to use chosen.removeAllChildren(); # the top of the code but it didnt remove anything. what should i do?
Your model is correct, but JTree is operating on old information.
The removeAllChildren() method removes the children, but it does not fire any events and the model.insertNodeInto() does fire insert events. So, JTree sees the nodes being added, but never sees the nodes being removed.
After adding the new children, try calling model.reload(chosen) to invalidate the tree below chosen.
Since you will be reloading the branch, you can also change model.insertNodeInto(dir, chosen,0) to chosen.insert(dir,0). That reduces the number of events posted.
Calling removeAllChildren() will remove the children from the node. There must be something else happening here that is creating duplicates. Make sure you are not calling anything twice and that you are refreshing the display of the tree.
In my application also i just fact the same problem. For that i just used the following code.
JTree.removeAll();
JTree.setModel(null);
It remove all child nodes from my Jtree.