Highlighting a JTree node works under the hood, but not visually
In my application, I show a JTree on the left side and if the user double clicks on a leaf, the corresponding data is loaded on the right side. At the time of loading this data, I (i) save the existing document (not relevant here), (ii) update the tree to account for any changes that may have happened, (iii) make sure the right node is selected in the tree after updating (i.e. the node the user double-clicked on) and (iv) load the selected node. The application logic works fine, i.e. the correct file is loaded and we therefore know that the correct node is selected in the tree, but visually no node is selected at all after the aforementioned steps.
I am aware of this question but the problem there seems to have been that the tree was not in focus. I have already tried the different remedies suggested in that post but have not been able to solve my problem. (There is also this related forum thread, although the site seems to be down right now. Furthermore, this question seems to be similar on the surface but the problem there stems from OP building a proprietary renderer.)
Please see below my code; I tried to reduce it to a SSCCE but I'm still stuck. My best guess at this time is that the problem has to do with the fact that a completely new TreeModel is created and loaded into the tree every time updateTree
is called and that this somehow makes it impossible to visually select the right node. If this were indeed to be the case, then one potential solution would be to alter the TreeModel instead of re-creating it from scratch but (i) that's less convenient for me and (ii) I believe this presents an interesting problem in its own right.
public class JTree_Problem_SSCCE
extends JFrame
private final JTree tree;
public JTree_Problem_SSCCE()
super("XYZ");
// Tree to select data
DefaultTreeModel treeModel = getTreeModel();
this.tree = new JTree(treeModel);
// I don't allow the user to select more than one node at a time but I can reproduce the problem with or without this
//TreeSelectionModel tsm = new DefaultTreeSelectionModel();
//tsm.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
//tree.setSelectionModel(tsm);
tree.addMouseListener(new TreeMouseAdapter());
expandAllTreeNodes();
getContentPane().add(tree,BorderLayout.WEST);
setLocation(25,25);
setSize(1700,1000);
setVisible(true);
private DefaultTreeModel getTreeModel()
DefaultMutableTreeNode n1 = new DefaultMutableTreeNode("Root");
DefaultMutableTreeNode n2 = new DefaultMutableTreeNode("Child 1");
DefaultMutableTreeNode n3 = new DefaultMutableTreeNode("Child 2");
n1.add(n2);
n1.add(n3);
return new DefaultTreeModel(n1);
private void updateTree(DefaultMutableTreeNode treeNode)
DefaultTreeModel dtm = getTreeModel();
tree.setModel(dtm);
expandAllTreeNodes();
// No idea why the below doesn't work visually (the application logic works just fine but no tree node is actually selected)
System.err.println(tree.getExpandsSelectedPaths()); // always returns true (I've seen this to be the problem in other questions)
System.err.println(new TreePath(((DefaultTreeModel)tree.getModel()).getPathToRoot(treeNode)));
if (treeNode != null)
tree.setSelectionPath(new TreePath(((DefaultTreeModel)tree.getModel()).getPathToRoot(treeNode)));
// As recommended in the answers here (https://stackoverflow.com/q/8896678/8031521),
// I have tried the below but to no avail
// tree.requestFocus(); // I have also tried requestFocusInWindow
// SwingUtilities.invokeLater(new Runnable()
// @Override
// public void run()
//
// tree.setSelectionPath(new TreePath(((DefaultTreeModel)tree.getModel()).getPathToRoot(treeNode)));
//
// );
private void expandAllTreeNodes()
// Expand all the nodes in the tree
// See https://stackoverflow.com/a/15211697/8031521
for (int i = 0; i < tree.getRowCount(); i++)
tree.expandRow(i);
class TreeMouseAdapter
extends MouseAdapter
@Override
public void mouseClicked(MouseEvent e)
if (e.getClickCount() == 2 &&
((DefaultMutableTreeNode)tree.getLastSelectedPathComponent()).isLeaf())
// [Before opening the new file, save the old one]
// After saving the old file, make sure the tree is up to date
updateTree((DefaultMutableTreeNode)tree.getLastSelectedPathComponent());
// [Now we open the new file]
java swing jtree
add a comment |
In my application, I show a JTree on the left side and if the user double clicks on a leaf, the corresponding data is loaded on the right side. At the time of loading this data, I (i) save the existing document (not relevant here), (ii) update the tree to account for any changes that may have happened, (iii) make sure the right node is selected in the tree after updating (i.e. the node the user double-clicked on) and (iv) load the selected node. The application logic works fine, i.e. the correct file is loaded and we therefore know that the correct node is selected in the tree, but visually no node is selected at all after the aforementioned steps.
I am aware of this question but the problem there seems to have been that the tree was not in focus. I have already tried the different remedies suggested in that post but have not been able to solve my problem. (There is also this related forum thread, although the site seems to be down right now. Furthermore, this question seems to be similar on the surface but the problem there stems from OP building a proprietary renderer.)
Please see below my code; I tried to reduce it to a SSCCE but I'm still stuck. My best guess at this time is that the problem has to do with the fact that a completely new TreeModel is created and loaded into the tree every time updateTree
is called and that this somehow makes it impossible to visually select the right node. If this were indeed to be the case, then one potential solution would be to alter the TreeModel instead of re-creating it from scratch but (i) that's less convenient for me and (ii) I believe this presents an interesting problem in its own right.
public class JTree_Problem_SSCCE
extends JFrame
private final JTree tree;
public JTree_Problem_SSCCE()
super("XYZ");
// Tree to select data
DefaultTreeModel treeModel = getTreeModel();
this.tree = new JTree(treeModel);
// I don't allow the user to select more than one node at a time but I can reproduce the problem with or without this
//TreeSelectionModel tsm = new DefaultTreeSelectionModel();
//tsm.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
//tree.setSelectionModel(tsm);
tree.addMouseListener(new TreeMouseAdapter());
expandAllTreeNodes();
getContentPane().add(tree,BorderLayout.WEST);
setLocation(25,25);
setSize(1700,1000);
setVisible(true);
private DefaultTreeModel getTreeModel()
DefaultMutableTreeNode n1 = new DefaultMutableTreeNode("Root");
DefaultMutableTreeNode n2 = new DefaultMutableTreeNode("Child 1");
DefaultMutableTreeNode n3 = new DefaultMutableTreeNode("Child 2");
n1.add(n2);
n1.add(n3);
return new DefaultTreeModel(n1);
private void updateTree(DefaultMutableTreeNode treeNode)
DefaultTreeModel dtm = getTreeModel();
tree.setModel(dtm);
expandAllTreeNodes();
// No idea why the below doesn't work visually (the application logic works just fine but no tree node is actually selected)
System.err.println(tree.getExpandsSelectedPaths()); // always returns true (I've seen this to be the problem in other questions)
System.err.println(new TreePath(((DefaultTreeModel)tree.getModel()).getPathToRoot(treeNode)));
if (treeNode != null)
tree.setSelectionPath(new TreePath(((DefaultTreeModel)tree.getModel()).getPathToRoot(treeNode)));
// As recommended in the answers here (https://stackoverflow.com/q/8896678/8031521),
// I have tried the below but to no avail
// tree.requestFocus(); // I have also tried requestFocusInWindow
// SwingUtilities.invokeLater(new Runnable()
// @Override
// public void run()
//
// tree.setSelectionPath(new TreePath(((DefaultTreeModel)tree.getModel()).getPathToRoot(treeNode)));
//
// );
private void expandAllTreeNodes()
// Expand all the nodes in the tree
// See https://stackoverflow.com/a/15211697/8031521
for (int i = 0; i < tree.getRowCount(); i++)
tree.expandRow(i);
class TreeMouseAdapter
extends MouseAdapter
@Override
public void mouseClicked(MouseEvent e)
if (e.getClickCount() == 2 &&
((DefaultMutableTreeNode)tree.getLastSelectedPathComponent()).isLeaf())
// [Before opening the new file, save the old one]
// After saving the old file, make sure the tree is up to date
updateTree((DefaultMutableTreeNode)tree.getLastSelectedPathComponent());
// [Now we open the new file]
java swing jtree
2
tree.setModel(dtm);
seems a little heavy handed in theupdateTree
method. The model should have generated appropriate notifications to the state change as required
– MadProgrammer
Nov 14 '18 at 3:57
1
Changing the model instance blows the selection model away, so no surprise the selection is not kept.
– Laurent G
Nov 14 '18 at 12:52
@MadProgrammer Yes, that is the hypothesis that I tried to articulate in my third paragraph. Do you know if there's a workaround for this or will I have to fix the underlying problem by changing the tree model instead of just re-creating it?
– Candamir
Nov 14 '18 at 14:51
add a comment |
In my application, I show a JTree on the left side and if the user double clicks on a leaf, the corresponding data is loaded on the right side. At the time of loading this data, I (i) save the existing document (not relevant here), (ii) update the tree to account for any changes that may have happened, (iii) make sure the right node is selected in the tree after updating (i.e. the node the user double-clicked on) and (iv) load the selected node. The application logic works fine, i.e. the correct file is loaded and we therefore know that the correct node is selected in the tree, but visually no node is selected at all after the aforementioned steps.
I am aware of this question but the problem there seems to have been that the tree was not in focus. I have already tried the different remedies suggested in that post but have not been able to solve my problem. (There is also this related forum thread, although the site seems to be down right now. Furthermore, this question seems to be similar on the surface but the problem there stems from OP building a proprietary renderer.)
Please see below my code; I tried to reduce it to a SSCCE but I'm still stuck. My best guess at this time is that the problem has to do with the fact that a completely new TreeModel is created and loaded into the tree every time updateTree
is called and that this somehow makes it impossible to visually select the right node. If this were indeed to be the case, then one potential solution would be to alter the TreeModel instead of re-creating it from scratch but (i) that's less convenient for me and (ii) I believe this presents an interesting problem in its own right.
public class JTree_Problem_SSCCE
extends JFrame
private final JTree tree;
public JTree_Problem_SSCCE()
super("XYZ");
// Tree to select data
DefaultTreeModel treeModel = getTreeModel();
this.tree = new JTree(treeModel);
// I don't allow the user to select more than one node at a time but I can reproduce the problem with or without this
//TreeSelectionModel tsm = new DefaultTreeSelectionModel();
//tsm.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
//tree.setSelectionModel(tsm);
tree.addMouseListener(new TreeMouseAdapter());
expandAllTreeNodes();
getContentPane().add(tree,BorderLayout.WEST);
setLocation(25,25);
setSize(1700,1000);
setVisible(true);
private DefaultTreeModel getTreeModel()
DefaultMutableTreeNode n1 = new DefaultMutableTreeNode("Root");
DefaultMutableTreeNode n2 = new DefaultMutableTreeNode("Child 1");
DefaultMutableTreeNode n3 = new DefaultMutableTreeNode("Child 2");
n1.add(n2);
n1.add(n3);
return new DefaultTreeModel(n1);
private void updateTree(DefaultMutableTreeNode treeNode)
DefaultTreeModel dtm = getTreeModel();
tree.setModel(dtm);
expandAllTreeNodes();
// No idea why the below doesn't work visually (the application logic works just fine but no tree node is actually selected)
System.err.println(tree.getExpandsSelectedPaths()); // always returns true (I've seen this to be the problem in other questions)
System.err.println(new TreePath(((DefaultTreeModel)tree.getModel()).getPathToRoot(treeNode)));
if (treeNode != null)
tree.setSelectionPath(new TreePath(((DefaultTreeModel)tree.getModel()).getPathToRoot(treeNode)));
// As recommended in the answers here (https://stackoverflow.com/q/8896678/8031521),
// I have tried the below but to no avail
// tree.requestFocus(); // I have also tried requestFocusInWindow
// SwingUtilities.invokeLater(new Runnable()
// @Override
// public void run()
//
// tree.setSelectionPath(new TreePath(((DefaultTreeModel)tree.getModel()).getPathToRoot(treeNode)));
//
// );
private void expandAllTreeNodes()
// Expand all the nodes in the tree
// See https://stackoverflow.com/a/15211697/8031521
for (int i = 0; i < tree.getRowCount(); i++)
tree.expandRow(i);
class TreeMouseAdapter
extends MouseAdapter
@Override
public void mouseClicked(MouseEvent e)
if (e.getClickCount() == 2 &&
((DefaultMutableTreeNode)tree.getLastSelectedPathComponent()).isLeaf())
// [Before opening the new file, save the old one]
// After saving the old file, make sure the tree is up to date
updateTree((DefaultMutableTreeNode)tree.getLastSelectedPathComponent());
// [Now we open the new file]
java swing jtree
In my application, I show a JTree on the left side and if the user double clicks on a leaf, the corresponding data is loaded on the right side. At the time of loading this data, I (i) save the existing document (not relevant here), (ii) update the tree to account for any changes that may have happened, (iii) make sure the right node is selected in the tree after updating (i.e. the node the user double-clicked on) and (iv) load the selected node. The application logic works fine, i.e. the correct file is loaded and we therefore know that the correct node is selected in the tree, but visually no node is selected at all after the aforementioned steps.
I am aware of this question but the problem there seems to have been that the tree was not in focus. I have already tried the different remedies suggested in that post but have not been able to solve my problem. (There is also this related forum thread, although the site seems to be down right now. Furthermore, this question seems to be similar on the surface but the problem there stems from OP building a proprietary renderer.)
Please see below my code; I tried to reduce it to a SSCCE but I'm still stuck. My best guess at this time is that the problem has to do with the fact that a completely new TreeModel is created and loaded into the tree every time updateTree
is called and that this somehow makes it impossible to visually select the right node. If this were indeed to be the case, then one potential solution would be to alter the TreeModel instead of re-creating it from scratch but (i) that's less convenient for me and (ii) I believe this presents an interesting problem in its own right.
public class JTree_Problem_SSCCE
extends JFrame
private final JTree tree;
public JTree_Problem_SSCCE()
super("XYZ");
// Tree to select data
DefaultTreeModel treeModel = getTreeModel();
this.tree = new JTree(treeModel);
// I don't allow the user to select more than one node at a time but I can reproduce the problem with or without this
//TreeSelectionModel tsm = new DefaultTreeSelectionModel();
//tsm.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
//tree.setSelectionModel(tsm);
tree.addMouseListener(new TreeMouseAdapter());
expandAllTreeNodes();
getContentPane().add(tree,BorderLayout.WEST);
setLocation(25,25);
setSize(1700,1000);
setVisible(true);
private DefaultTreeModel getTreeModel()
DefaultMutableTreeNode n1 = new DefaultMutableTreeNode("Root");
DefaultMutableTreeNode n2 = new DefaultMutableTreeNode("Child 1");
DefaultMutableTreeNode n3 = new DefaultMutableTreeNode("Child 2");
n1.add(n2);
n1.add(n3);
return new DefaultTreeModel(n1);
private void updateTree(DefaultMutableTreeNode treeNode)
DefaultTreeModel dtm = getTreeModel();
tree.setModel(dtm);
expandAllTreeNodes();
// No idea why the below doesn't work visually (the application logic works just fine but no tree node is actually selected)
System.err.println(tree.getExpandsSelectedPaths()); // always returns true (I've seen this to be the problem in other questions)
System.err.println(new TreePath(((DefaultTreeModel)tree.getModel()).getPathToRoot(treeNode)));
if (treeNode != null)
tree.setSelectionPath(new TreePath(((DefaultTreeModel)tree.getModel()).getPathToRoot(treeNode)));
// As recommended in the answers here (https://stackoverflow.com/q/8896678/8031521),
// I have tried the below but to no avail
// tree.requestFocus(); // I have also tried requestFocusInWindow
// SwingUtilities.invokeLater(new Runnable()
// @Override
// public void run()
//
// tree.setSelectionPath(new TreePath(((DefaultTreeModel)tree.getModel()).getPathToRoot(treeNode)));
//
// );
private void expandAllTreeNodes()
// Expand all the nodes in the tree
// See https://stackoverflow.com/a/15211697/8031521
for (int i = 0; i < tree.getRowCount(); i++)
tree.expandRow(i);
class TreeMouseAdapter
extends MouseAdapter
@Override
public void mouseClicked(MouseEvent e)
if (e.getClickCount() == 2 &&
((DefaultMutableTreeNode)tree.getLastSelectedPathComponent()).isLeaf())
// [Before opening the new file, save the old one]
// After saving the old file, make sure the tree is up to date
updateTree((DefaultMutableTreeNode)tree.getLastSelectedPathComponent());
// [Now we open the new file]
java swing jtree
java swing jtree
asked Nov 14 '18 at 1:17
CandamirCandamir
454619
454619
2
tree.setModel(dtm);
seems a little heavy handed in theupdateTree
method. The model should have generated appropriate notifications to the state change as required
– MadProgrammer
Nov 14 '18 at 3:57
1
Changing the model instance blows the selection model away, so no surprise the selection is not kept.
– Laurent G
Nov 14 '18 at 12:52
@MadProgrammer Yes, that is the hypothesis that I tried to articulate in my third paragraph. Do you know if there's a workaround for this or will I have to fix the underlying problem by changing the tree model instead of just re-creating it?
– Candamir
Nov 14 '18 at 14:51
add a comment |
2
tree.setModel(dtm);
seems a little heavy handed in theupdateTree
method. The model should have generated appropriate notifications to the state change as required
– MadProgrammer
Nov 14 '18 at 3:57
1
Changing the model instance blows the selection model away, so no surprise the selection is not kept.
– Laurent G
Nov 14 '18 at 12:52
@MadProgrammer Yes, that is the hypothesis that I tried to articulate in my third paragraph. Do you know if there's a workaround for this or will I have to fix the underlying problem by changing the tree model instead of just re-creating it?
– Candamir
Nov 14 '18 at 14:51
2
2
tree.setModel(dtm);
seems a little heavy handed in the updateTree
method. The model should have generated appropriate notifications to the state change as required– MadProgrammer
Nov 14 '18 at 3:57
tree.setModel(dtm);
seems a little heavy handed in the updateTree
method. The model should have generated appropriate notifications to the state change as required– MadProgrammer
Nov 14 '18 at 3:57
1
1
Changing the model instance blows the selection model away, so no surprise the selection is not kept.
– Laurent G
Nov 14 '18 at 12:52
Changing the model instance blows the selection model away, so no surprise the selection is not kept.
– Laurent G
Nov 14 '18 at 12:52
@MadProgrammer Yes, that is the hypothesis that I tried to articulate in my third paragraph. Do you know if there's a workaround for this or will I have to fix the underlying problem by changing the tree model instead of just re-creating it?
– Candamir
Nov 14 '18 at 14:51
@MadProgrammer Yes, that is the hypothesis that I tried to articulate in my third paragraph. Do you know if there's a workaround for this or will I have to fix the underlying problem by changing the tree model instead of just re-creating it?
– Candamir
Nov 14 '18 at 14:51
add a comment |
1 Answer
1
active
oldest
votes
The problem is related to creating a brand new TreeModel
on every call to updateTree
. The problem is that the treeNode
variable refers to a node in the old tree. Therefore, there is no path from the root of the new tree, to the node in old tree (i.e., Calling getParent()
multiple times starting from treeNode
will lead to the root of the old tree and not the new one). I see two potential options to solve your problem.
Option 1: Search for new tree node
You can write a function like the one below to search for the tree node starting from the new root with the path of the old treeNode
.
private static DefaultMutableTreeNode searchTree(DefaultMutableTreeNode root, Object path)
if (!root.getUserObject().equals(path[0]))
// completely different root
// potentially problematic
return null;
DefaultMutableTreeNode node = root;
for (int i = 1; i < path.length; ++i)
Object searchItem = path[i];
Enumeration<TreeNode> children = node.children();
boolean found = false;
while (children.hasMoreElements())
DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement();
if (searchItem.equals(child.getUserObject()))
found = true;
node = child;
break;
if (!found)
// path does not exist any more
// potentially problematic
return null;
return node;
You would then add the following to the updateTree
method before setting the tree selection path.
treeNode = searchTree((DefaultMutableTreeNode) tree.getModel().getRoot(), treeNode.getUserObjectPath());
Option 2: Modify existing tree
Instead of creating a new tree model every time modify the existing one. For each directory start by creating a set of files in the directory and a set of tree nodes for the directory in tree. Remove all tree nodes for files that are not in the directory. Then, create nodes for all files in the directory that are not already in the tree. This option may be more complex that option 1, but it does not create potential problems with duplicate tree nodes through out your code.
Thanks, it works like a charm and I like the level of detail in your answer. The one caveat - which you mentioned - is that yoursearchTree
method may not return a "copy" of the correct node in the new model if you have multiple nodes with the same label at the same location in the tree (not a problem in my case since the application logic ensures that all children of any given leaf are unique but anyone coming across this answer should be aware of the issue).
– Candamir
Nov 20 '18 at 0:00
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53291818%2fhighlighting-a-jtree-node-works-under-the-hood-but-not-visually%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
The problem is related to creating a brand new TreeModel
on every call to updateTree
. The problem is that the treeNode
variable refers to a node in the old tree. Therefore, there is no path from the root of the new tree, to the node in old tree (i.e., Calling getParent()
multiple times starting from treeNode
will lead to the root of the old tree and not the new one). I see two potential options to solve your problem.
Option 1: Search for new tree node
You can write a function like the one below to search for the tree node starting from the new root with the path of the old treeNode
.
private static DefaultMutableTreeNode searchTree(DefaultMutableTreeNode root, Object path)
if (!root.getUserObject().equals(path[0]))
// completely different root
// potentially problematic
return null;
DefaultMutableTreeNode node = root;
for (int i = 1; i < path.length; ++i)
Object searchItem = path[i];
Enumeration<TreeNode> children = node.children();
boolean found = false;
while (children.hasMoreElements())
DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement();
if (searchItem.equals(child.getUserObject()))
found = true;
node = child;
break;
if (!found)
// path does not exist any more
// potentially problematic
return null;
return node;
You would then add the following to the updateTree
method before setting the tree selection path.
treeNode = searchTree((DefaultMutableTreeNode) tree.getModel().getRoot(), treeNode.getUserObjectPath());
Option 2: Modify existing tree
Instead of creating a new tree model every time modify the existing one. For each directory start by creating a set of files in the directory and a set of tree nodes for the directory in tree. Remove all tree nodes for files that are not in the directory. Then, create nodes for all files in the directory that are not already in the tree. This option may be more complex that option 1, but it does not create potential problems with duplicate tree nodes through out your code.
Thanks, it works like a charm and I like the level of detail in your answer. The one caveat - which you mentioned - is that yoursearchTree
method may not return a "copy" of the correct node in the new model if you have multiple nodes with the same label at the same location in the tree (not a problem in my case since the application logic ensures that all children of any given leaf are unique but anyone coming across this answer should be aware of the issue).
– Candamir
Nov 20 '18 at 0:00
add a comment |
The problem is related to creating a brand new TreeModel
on every call to updateTree
. The problem is that the treeNode
variable refers to a node in the old tree. Therefore, there is no path from the root of the new tree, to the node in old tree (i.e., Calling getParent()
multiple times starting from treeNode
will lead to the root of the old tree and not the new one). I see two potential options to solve your problem.
Option 1: Search for new tree node
You can write a function like the one below to search for the tree node starting from the new root with the path of the old treeNode
.
private static DefaultMutableTreeNode searchTree(DefaultMutableTreeNode root, Object path)
if (!root.getUserObject().equals(path[0]))
// completely different root
// potentially problematic
return null;
DefaultMutableTreeNode node = root;
for (int i = 1; i < path.length; ++i)
Object searchItem = path[i];
Enumeration<TreeNode> children = node.children();
boolean found = false;
while (children.hasMoreElements())
DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement();
if (searchItem.equals(child.getUserObject()))
found = true;
node = child;
break;
if (!found)
// path does not exist any more
// potentially problematic
return null;
return node;
You would then add the following to the updateTree
method before setting the tree selection path.
treeNode = searchTree((DefaultMutableTreeNode) tree.getModel().getRoot(), treeNode.getUserObjectPath());
Option 2: Modify existing tree
Instead of creating a new tree model every time modify the existing one. For each directory start by creating a set of files in the directory and a set of tree nodes for the directory in tree. Remove all tree nodes for files that are not in the directory. Then, create nodes for all files in the directory that are not already in the tree. This option may be more complex that option 1, but it does not create potential problems with duplicate tree nodes through out your code.
Thanks, it works like a charm and I like the level of detail in your answer. The one caveat - which you mentioned - is that yoursearchTree
method may not return a "copy" of the correct node in the new model if you have multiple nodes with the same label at the same location in the tree (not a problem in my case since the application logic ensures that all children of any given leaf are unique but anyone coming across this answer should be aware of the issue).
– Candamir
Nov 20 '18 at 0:00
add a comment |
The problem is related to creating a brand new TreeModel
on every call to updateTree
. The problem is that the treeNode
variable refers to a node in the old tree. Therefore, there is no path from the root of the new tree, to the node in old tree (i.e., Calling getParent()
multiple times starting from treeNode
will lead to the root of the old tree and not the new one). I see two potential options to solve your problem.
Option 1: Search for new tree node
You can write a function like the one below to search for the tree node starting from the new root with the path of the old treeNode
.
private static DefaultMutableTreeNode searchTree(DefaultMutableTreeNode root, Object path)
if (!root.getUserObject().equals(path[0]))
// completely different root
// potentially problematic
return null;
DefaultMutableTreeNode node = root;
for (int i = 1; i < path.length; ++i)
Object searchItem = path[i];
Enumeration<TreeNode> children = node.children();
boolean found = false;
while (children.hasMoreElements())
DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement();
if (searchItem.equals(child.getUserObject()))
found = true;
node = child;
break;
if (!found)
// path does not exist any more
// potentially problematic
return null;
return node;
You would then add the following to the updateTree
method before setting the tree selection path.
treeNode = searchTree((DefaultMutableTreeNode) tree.getModel().getRoot(), treeNode.getUserObjectPath());
Option 2: Modify existing tree
Instead of creating a new tree model every time modify the existing one. For each directory start by creating a set of files in the directory and a set of tree nodes for the directory in tree. Remove all tree nodes for files that are not in the directory. Then, create nodes for all files in the directory that are not already in the tree. This option may be more complex that option 1, but it does not create potential problems with duplicate tree nodes through out your code.
The problem is related to creating a brand new TreeModel
on every call to updateTree
. The problem is that the treeNode
variable refers to a node in the old tree. Therefore, there is no path from the root of the new tree, to the node in old tree (i.e., Calling getParent()
multiple times starting from treeNode
will lead to the root of the old tree and not the new one). I see two potential options to solve your problem.
Option 1: Search for new tree node
You can write a function like the one below to search for the tree node starting from the new root with the path of the old treeNode
.
private static DefaultMutableTreeNode searchTree(DefaultMutableTreeNode root, Object path)
if (!root.getUserObject().equals(path[0]))
// completely different root
// potentially problematic
return null;
DefaultMutableTreeNode node = root;
for (int i = 1; i < path.length; ++i)
Object searchItem = path[i];
Enumeration<TreeNode> children = node.children();
boolean found = false;
while (children.hasMoreElements())
DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement();
if (searchItem.equals(child.getUserObject()))
found = true;
node = child;
break;
if (!found)
// path does not exist any more
// potentially problematic
return null;
return node;
You would then add the following to the updateTree
method before setting the tree selection path.
treeNode = searchTree((DefaultMutableTreeNode) tree.getModel().getRoot(), treeNode.getUserObjectPath());
Option 2: Modify existing tree
Instead of creating a new tree model every time modify the existing one. For each directory start by creating a set of files in the directory and a set of tree nodes for the directory in tree. Remove all tree nodes for files that are not in the directory. Then, create nodes for all files in the directory that are not already in the tree. This option may be more complex that option 1, but it does not create potential problems with duplicate tree nodes through out your code.
answered Nov 19 '18 at 20:47
DragonAssassinDragonAssassin
6061811
6061811
Thanks, it works like a charm and I like the level of detail in your answer. The one caveat - which you mentioned - is that yoursearchTree
method may not return a "copy" of the correct node in the new model if you have multiple nodes with the same label at the same location in the tree (not a problem in my case since the application logic ensures that all children of any given leaf are unique but anyone coming across this answer should be aware of the issue).
– Candamir
Nov 20 '18 at 0:00
add a comment |
Thanks, it works like a charm and I like the level of detail in your answer. The one caveat - which you mentioned - is that yoursearchTree
method may not return a "copy" of the correct node in the new model if you have multiple nodes with the same label at the same location in the tree (not a problem in my case since the application logic ensures that all children of any given leaf are unique but anyone coming across this answer should be aware of the issue).
– Candamir
Nov 20 '18 at 0:00
Thanks, it works like a charm and I like the level of detail in your answer. The one caveat - which you mentioned - is that your
searchTree
method may not return a "copy" of the correct node in the new model if you have multiple nodes with the same label at the same location in the tree (not a problem in my case since the application logic ensures that all children of any given leaf are unique but anyone coming across this answer should be aware of the issue).– Candamir
Nov 20 '18 at 0:00
Thanks, it works like a charm and I like the level of detail in your answer. The one caveat - which you mentioned - is that your
searchTree
method may not return a "copy" of the correct node in the new model if you have multiple nodes with the same label at the same location in the tree (not a problem in my case since the application logic ensures that all children of any given leaf are unique but anyone coming across this answer should be aware of the issue).– Candamir
Nov 20 '18 at 0:00
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53291818%2fhighlighting-a-jtree-node-works-under-the-hood-but-not-visually%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
tree.setModel(dtm);
seems a little heavy handed in theupdateTree
method. The model should have generated appropriate notifications to the state change as required– MadProgrammer
Nov 14 '18 at 3:57
1
Changing the model instance blows the selection model away, so no surprise the selection is not kept.
– Laurent G
Nov 14 '18 at 12:52
@MadProgrammer Yes, that is the hypothesis that I tried to articulate in my third paragraph. Do you know if there's a workaround for this or will I have to fix the underlying problem by changing the tree model instead of just re-creating it?
– Candamir
Nov 14 '18 at 14:51