change the jtree node text runtime - java

I am trying to create a JTree in java swing now i want to change the node text at runtime
try
{
int a=1,b=2,c=3;
DefaultMutableTreeNode root =
new DefaultMutableTreeNode("A"+a);
DefaultMutableTreeNode child[]=new DefaultMutableTreeNode[1];
DefaultMutableTreeNode grandChild[]= new DefaultMutableTreeNode[1];
child[0] = new DefaultMutableTreeNode("Central Excise"+b);
grandChild[0]=new DefaultMutableTreeNode("CE Acts: "+c);
child[0].add(grandChild[0]);
root.add(child[0]);
tree = new JTree(root);
}
catch(Exception ex)
{
ex.printStackTrace()
}
Now i want later on how can i change A 1 to a 2 dynamically and similarly in child and grand child nodes

You are looking for javax.swing.tree.DefaultMutableTreeNode.setUserObject(Object)
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
root.setUserObject("My label");
model.nodeChanged(root);
This assumes that you are using the DefautltTreeModel.

If you're not using a custom TreeModel, then the model of your tree is a DefaultTreeModel.
You'll need to walk the tree with some kind of comparator, given your DefaultMutableTreeNode getUserObject() (string or whatever) to achieve what you want.
You have 2 simple options accordingly to your question and the code that you pasted :
If your change is triggered by let's say a click event, you can get the selection and walk the tree from there.
Otherwise you'll need to walk the tree from the root
Upon successful changes, you'll need to fire events from the model that will trigger later a repaint of the view (nodesWereInserted, etc.).
Hope it helps

Related

Only handling tree will expand but not tree selection in JTree - Java Swing

I am doing lazy loading for my app. I want a node to load only user click to it's icon. The point is i don't know that node have it's children or not.My temporary solution is to define a node having children then loading them based on selection event, i don't use tree will expand event for lazy loading. Is there any ways for me to just implement treeWillExpand event. You can reference in TreeWillExpanListener and TreeExpandEventDemo2.
// Have a tree with some unexpanded root items
// When an item is expanded, add some children
tree.addListener(new Tree.ExpandListener() {
public void nodeExpand(ExpandEvent event) {
// No children for the first node
if (!hasChildren(event.getItemId())) {
tree.setChildrenAllowed(event.getItemId(), false);
} else {
// Add a few new child nodes to the expanded node
tree.addItem(childId);
tree.setParent(childId, event.getItemId());
}
}
});
you can implement hasChildren to find the child based on tree node being expanded and then find child and add

DefaultMutableTreeNode icon

I have a JTree displayed in a JContentPane built from DefaultMutableTreeNode objects. The tree is intented to display the local file-system. The data should be loaded on request, therefore when the user wants to expand it. This works well, but as long as there are no child items in the node, it displays a file-icon, and turns into a folder-icon when child items have been inserted.
How can I make the node display a folder-icon always, although there are (yet) no child items?
You need to implement cell renderer for your tree. So you can define icon for the node.
See here the sample for a table (tree also has method setCellRenderer)
Using a DefaultMutableTreeNode (or a custom implementation of TreeNode), the means to distinguish files from empty folders is its allowsChildren property:
// get a list of files
File[] files = new File(".").listFiles();
// configure the nodes' allowsChildren as the isDir of the File object
for (File file : files) {
root.add(new DefaultMutableTreeNode(file, file.isDirectory()));
}
// configure the TreeModel to use nodes' allowsChildren property to
// decide on its leaf-ness
DefaultTreeModel model = new DefaultTreeModel(root, true);
I use this:
DefaultMutableTreeNode root = new DefaultMutableTreeNode ();
DefaultTreeModel treeModel = new DefaultTreeModel (root);
tree = new JTree (treeModel);
addFiles (root); // build the catalog tree recursively
treeModel.setAsksAllowsChildren (true); // allows empty nodes to appear as folders
with
if (file.isDirectory ())
newNode.setAllowsChildren (true);
in the addFiles() routine. The setAsksAllowsChildren(true) needs to come after the tree is built.

A editable JTree converts the tree nodes into Strings

I'm using a JTree that is populated from a database.
The tree is created by setting the root node and its childs with custom objects this way:
private DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Categorias");
...
ResultSet primaryCategories = dbm.fetchAllCategories();
while (primaryCategories.next()){
Category category = new Category(primaryCategories.getLong("_id"),
primaryCategories.getString("category"));
DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(category);
rootNode.add(childNode);
ResultSet currentSubcategory = dbm.fetchChildSubcategories(category.getCatId());
while (currentSubcategory.next()){
Category subcategory = new Category(currentSubcategory.getLong("_id"),
currentSubcategory.getString("category"));
childNode.add(new DefaultMutableTreeNode(subcategory, false));
}
}
...
After this, the tree is perfectly created. Populated with "Category" Objects, every object has its own ID number and its name to use in toString() method.
The problem comes when it's set editable. Once the node is renamed, the Category node is also converted into a String Object, so I cant update the new Category name value to the database.
I've tried to capture the renaming event with treeNodesChanged(TreeModelEvent e) but, the userObject is already changed to a String Object, and can't get a referece of what object was edited.
What way can I solve this? Should I have a copy of the tree that's shown and another of the downloaded from the database and uptade both everytime a change occurs?
*PD: *
I also tried to capture the changed node from the model overriding the method:
public void nodeChanged(TreeNode newNode) {
DefaultMutableTreeNode parent = ((DefaultMutableTreeNode)newNode.getParent());
int index = getIndexOfChild(parent, newNode);
DefaultMutableTreeNode oldNode = (DefaultMutableTreeNode) getChild(parent, index);
System.out.println(parent.getUserObject().getClass().toString());
System.out.println(oldNode.getUserObject().getClass().toString());
}
this prints:
class com.giorgi.commandserver.entity.Category
class java.lang.String
So the old node here has already been changed to a String and I've lost completely the reference to the older Category and its ID so I cannot update it in the database.
Any help is wellcome.
Okay, that took a bit of digging.
Basically, when the editing is "stopped", the JTree will request the editor's value via editor's getCellEditorValue. This is then passed to the model via the valuesForPathChanged method, which finally calls the node's setUserObject method.
Presumably, you are using either the default editor or one based on text field. This will return a String value.
What you need to do is trap the change to the setUserObject method of your tree node, access the value coming (ie, check if it's a String or not) and update as required.
Final solution was as MadProgrammer said to get it in:
public void valueForPathChanged(TreePath path, Object newValue) {
DefaultMutableTreeNode aNode = (DefaultMutableTreeNode)path.getLastPathComponent();
Category catNode = (Category) aNode.getUserObject();
catNode.setCategory((String) newValue);
catNode.updateFromDatabase();
nodeChanged(aNode);
}

Select all checkbox nodes in a jtree

I have a checkbox node tree build based on a named vector .
And i have a button called select all .
When i click the select all button , i need all the nodes on the chekbox node tree to be selected .
The code i have used is
for (CheckBoxNode rowNode: CheckBoxNodeTree. checkBoxCoulmn)
{
if(rowNode instanceof CheckBoxNode)
rowNode.setSelected((true));
}
Here checkBoxColumn is a arraylist which contains all the nodes of the tree as (Node , isSelected) .
But when i do this , nothing happens to the tree.
I've done it by casting the tree node to a default mutable tree node and get an enumeration of the children. Then you can iterate through them and setSelected(true). Your way could run into problems with threading or concurrent modifications if the user repeatedly clicks.
Enumeration<TreeNode> children = ((DefaultMutableTreeNode) node).breadthFirstEnumeration();
while (children.hasMoreElements()) {
TreeNode child = children.nextElement();
Object currentNode = ((DefaultMutableTreeNode) child).getUserObject();
//cast your currentNode to the check box and set selected or unselected.
}
Also, are you doing this on the event dispath thread? If not that might be why you aren't seeing any updates to the screen.

manipulate jtree node via references seems not working (swing)

I have the following problem (this is related to my post blink a tree node):
I have a custom cell renderer.
In some part of my code I create a new DefaultMutableTreeNode and store it in a list
public static List<DefaultMutableTreeNode> nodes = new ArrayList<DefaultMutableTreeNode>()
//in some time
DefaultMutableTreeNode aNode = new DefaultMutableTreeNode("SomeValue");
nodes.add(node);
In my cell renderer I do:
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean selected, boolean expanded, boolean leaf, int row,
boolean hasFocus) {
DefaultMutableTreeNode n = (DefaultMutableTreeNode)value;
if(nodes.contains(n)){
//set background to red
}
}
At this point nodes has a node but the code never goes in the if branch.
Why? I can not understand since I already stored it in the arraylist. Do I get a different reference?
Also I created a swing timer:
Timer t = new Timer(400, new ActionListener(){
public void actionPerformed(ActionEvent evt) {
if(nodes.size == 0)
return;
TreePath p = new TreePath(nodes.get(0));
Rectangle r = tree.getPathBounds(p);
tree.repaint(r);
}
});
But I get a NPE in tree.getPathBounds.
I can not understand why. Can't I manipulate DefaultMutableNodes I stored in my list this way? What am I doing wrong in my thinking?
Note: If I simply call repaint(); in the timer and in the cell renderer I loop over the nodes to see if it displays the sametext with the node I have stored, what I want I get the blinking, works
Thanks
Actually TreePath is a list of objects... path from tree root to the node. If you create a path from the single node the path exists in the tree only if the node is root of the tree.
I woul recommend to use TreeSelectionEvent public TreePath[] getPaths() method. The method provides actual paths.
I don't think DefaultMutableTreeNode defines an equals method, so it might not find the match in your List of nodes. Try storing and searching for the user object or extends DefaultMutableTreeNode and define equals.

Categories

Resources