tags:

views:

96

answers:

1

It appears to me that tree selection events should happen after focus events, but this doesn't seem to be the case. Assume you have a JTree and a JTextField, where the JTextField is populated by what is selected in the tree. When the user changes the text field, on focus lost, you update the tree from the text field. however, the tree selection is changed before the focus is lost on the text field. this is incorrect, right? Any ideas? Here is some sample code:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class Focus extends JFrame
{
 public static void main(String[] args)
 {
  Focus f = new Focus();
  f.setLocationRelativeTo(null);
  f.setVisible(true);
 }

 public Focus()
 {
  Container cp = getContentPane();
  cp.setLayout(new BorderLayout());

  final JTextArea ta = new JTextArea(5, 10);
  cp.add(new JScrollPane(ta), BorderLayout.SOUTH);

  JSplitPane sp = new JSplitPane();
  cp.add(sp, BorderLayout.CENTER);

  JTree t = new JTree();
  t.addTreeSelectionListener(new TreeSelectionListener()
  {
   public void valueChanged(TreeSelectionEvent tse)
   {
    ta.append("Tree Selection changed\n");
   }
  });
  t.addFocusListener(new FocusListener()
  {
   public void focusGained(FocusEvent fe)
   {
    ta.append("Tree focus gained\n");
   }
   public void focusLost(FocusEvent fe)
   {
    ta.append("Tree focus lost\n");
   }
  });

  sp.setLeftComponent(new JScrollPane(t));
  JTextField f = new JTextField(10);
  sp.setRightComponent(f);

  pack();

  f.addFocusListener(new FocusListener()
  {
   public void focusGained(FocusEvent fe)
   {
    ta.append("Text field focus gained\n");
   }
    public void focusLost(FocusEvent fe)
{
    ta.append("Text field focus lost\n");
   }
  });
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 }
}
A: 

Have your text field listener invoke setSelectionPath() to select the TreePath for the node that matches the text. The methods of DefaultMutableTreeNode can be used to traverse the tree. I'd use an ActionListener on the text field, but a FocusListener should work—just don't rely on the the order in which TreeSelectionListener events arrive.

Here's an example of obtaining the "pizza" node in the default JTree:

JTree tree = new JTree();
TreeNode node = (TreeNode) tree.getModel().getRoot();
node = node.getChildAt(2).getChildAt(1);
TreePath pizza = new TreePath(((DefaultMutableTreeNode) node).getPath());
trashgod
no you misunderstand, perhaps i didn't explain. Whatever the user types in the text field, on loss of focus, should change the currently selected tree node.
MeBigFatGuy
IIUC, `setSelectionPath()` does exactly that when called from `focusLost()`: it changes the selection to the specified `TreePath`. If you're trying to edit a node, it might be easier to use `t.setEditable(true)`; this would allow editing *in situ*.
trashgod
the text field might say 'fooo' but there is no fooo in the tree. in fact it might not even be the node label that is being changed -- it might just be a field in the user object of the selected node.
MeBigFatGuy
It seems easy enough to check each user object while traversing the tree. I typically return null on failure; when passed to `setSelectionPath()`, null clears the selection.
trashgod