tags:

views:

311

answers:

2

I have a wizard with several screens where user has to fill his/her details for further processing. At the second screen I have a radio group with three radio buttons that enable additional elements. To proceed, user has to choose one of them. When user selects third button, single-selection JTree filled in with data enables and user has to select an option from it. Then user has to press "Next" to get to next screen. The option he\she had selected is stored as a TreePath. So far so good.

My problem is the following. If the user wants to come back from the following screen to the screen with a JTree, I want to provide him\her with the JTree expanded to the option that had been selected and to highlight the option. However, whatsoever I try to do for that (any combinations of expandPath, scrollPathToVisible, addSelectionPath, makeVisible) always provides me with a collapsed tree. I try to expand both leaves and nodes. My code looks like this:

rbProcessJTree.setSelected(isProcessJTree());

if (null != getSelectedTablePath()){
    trTables.addSelectionPath(getSelectedTablePath());
    trTables.expandPath(getSelectedTablePath());
    trTables.scrollPathToVisible(getSelectedTablePath());
}

When setSelected() is called, state change listener is invoked that enables JTree. The model is loaded during the form initialization.

Each time I switch between screens, I save the input data from previous screen and dispose it. Then, when I need to open previous screen back, I save data from the following screen, dispose it, load data to this screen and show it. So each time the screen is generating from scratch.

Could you please explain, what sequence of operations has to be done to get JTree expanded in a newly created form,with data model loaded and selection path provided?

+1  A: 

Here is some code I've used to record expansion and selected paths in JTree. You could record the state stuff here between Next and Back pages.

// record expanded nodes to reinstate later; 
TreePath rootPath= new TreePath(objectWeKnowIsAtRoot);

Enumeration<TreePath> expandedPaths = tree.getExpandedDescendants(rootPath);

// record current-selection - it's OK if it's null
TreePath selectedPath = tree.getSelectionPath();


// ******* do stuff that may, and often will, modify our tree content ********


// restore valid expansion paths (some may - correctly - have been removed in modifications)
while (expandedPaths != null && expandedPaths.hasMoreElements())
{
    TreePath path = expandedPaths.nextElement();
    if (isPathValid(path))
    {
        tree.expandPath(path);
    }
}

// restore selected path, if apt
if (isPathValid(selectedPath))
{
    tree.setSelectionPath(selectedPath);
}

The isValidPath() method used above is based on this one:

http://forums.sun.com/thread.jspa?threadID=567157&amp;tstart=38085

Brian
I have tried this approach, but it doesn't work either. Don't know the reason. Have later seen that paths returned in enumeration have random order, converted them to ArrayList and sorted starting from root, than tried with that. No chance. Added expandPath() for the selected path itself. No way. No ideas. Thanks for the response though.By the way, when I debug it, I see that for my selection path isVisible() is true but isExpanded() is false. Can it help?
Dzmitry Zhaleznichenka
Hmm; are you definitely doing the selection/expansion stuff after the data's been populated? What you could try is adding a "debug this" button to your wizard which, when pressed, does the selection/expansion, giving you a chance to confirm visually that yes all the data is present and correct first?
Brian
I will try in an hour or so, when finish with the current task. However, isPathValid() always returns true while debugging, and expandPath() method executes consequently in your algorithm. It should mean that data had been populated yet, isn't it?I populate the data model while initializing the form. Only after that I try to perform some actions with it. Maybe something has to be explored concerning my state change listener for a radio button. It fires for several times before I get to tree processing method.
Dzmitry Zhaleznichenka
I've had problems debugging lots of Swing code when listeners are firing multiple times. Definitely try the "debug me" button, also maybe worth using log4j or System.out to establish how many complete "cycles" it goes through, e.g. you might find things run correctly on a first run through, but they're actually getting wiped out / invalidated by a second run?
Brian
I added the button and also made a JTree always enabled to prevent state change listener possible effect. No changes, however. Are there any other suggestions?
Dzmitry Zhaleznichenka
Clutching at straws here, but from your original code I notice you call getSelectedTablePath() many times instead of doing an initial "path = getSelectedTablePath();". I wonder if getSelectedTablePath() can vary as you do operations on the tree, i.e. it's not just doing a "return path;" itself but is actually involving some calculation, and each time you call it you might get different content? I don't think this is really the problem but I guess it's worth ruling out...
Brian
+1  A: 

If you're using DefaultMutableTreeNode, you can always use an Enumeration to search for the TreeNode you want. Then setSelectionPath() should work if getExpandsSelectedPaths() is true.

Edit: I was thinking more like using an Enumeration from DefaultMutableTreeNode:

JTree tree = new JTree();
DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel().getRoot();
...
private TreePath find(DefaultMutableTreeNode root, String s) {
    Enumeration<DefaultMutableTreeNode> e = root.depthFirstEnumeration();
    while (e.hasMoreElements()) {
        // return match
    }
    return null;
}

Then you can do this:

TreePath path = find(root, "pizza");
tree.setSelectionPath(path);
tree.scrollPathToVisible(path);
Catalina Island
List<TreePath> tpa = treeStorage.getExpandedPathsList();if (null != tpa){ Collections.sort(tpa, new TreePathComparator()); for (TreePath t : tpa){ if (isPathValid(t)){ trTables.expandPath(t); } }}if (isPathValid(treeStorage.getSelectedTablePath())){ trTables.setSelectionPath(treeStorage.getSelectedTablePath()); System.out.println("expands:" +trTables.getExpandsSelectedPaths());}This code returns me true. However, the tree is still collapsed. Enumeration returns results in a random order and cannot be resetted so I changed it to ArrayList. Sorry for formatting.
Dzmitry Zhaleznichenka