Highlighting a JTree node works under the hood, but not visually










1















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]














share|improve this question

















  • 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






  • 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















1















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]














share|improve this question

















  • 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






  • 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













1












1








1


0






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]














share|improve this question














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






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 14 '18 at 1:17









CandamirCandamir

454619




454619







  • 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






  • 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





    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





    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












1 Answer
1






active

oldest

votes


















1





+50









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.






share|improve this answer























  • 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










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
);



);













draft saved

draft discarded


















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









1





+50









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.






share|improve this answer























  • 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















1





+50









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.






share|improve this answer























  • 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













1





+50







1





+50



1




+50





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.






share|improve this answer













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.







share|improve this answer












share|improve this answer



share|improve this answer










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 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
















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

















draft saved

draft discarded
















































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.




draft saved


draft discarded














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





















































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







這個網誌中的熱門文章

Barbados

How to read a connectionString WITH PROVIDER in .NET Core?

Node.js Script on GitHub Pages or Amazon S3