2009-08-14 11 views
2

C'est un suivi de ces questions précédentes:Java Swing: Comment appeler stopCellEditing() avant TreeListeners: valueChanged?

Lorsque j'utilise la propriété terminateEditOnFocusLost, comme ci-dessous, mon CellEditor arrête correctement le montage lorsque la table perd le focus :

jtable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); 

Il fonctionne également avec mes JButtons. La méthode stopCellEditing() est appelée pour mon TableCellEditor avant que l'action de presse de bouton est traitée. Mais quand je l'utilise avec un JTree, et la sélection de l'arbre change, la méthode TreeSelectionListener.valueChanged est appelée avantstopCellEditing().

Est-ce que quelqu'un sait s'il y a un moyen de forcer stopCellEditing() à être invoqué en premier, ou devrais-je juste faire un peu de contourner ce problème?

Répondre

1

JTree n'a pas de propriété client similaire dans Swing. Mais JXTree, une classe dérivée de JTree, en SwingX fait: invokeStopEditing.

Si vous ne pouvez pas utiliser SwingX, vous pouvez toujours regarder le code source de JXTree et de voir comment ce mécanisme de StopEditing fonctionne: JXTree SwingX 1.0 API Documentation and Javadoc(go to Source tab)

spécialement, à partir de la ligne 974, un écouteur est créé pour surveiller " permanentFocusOwner "changement de propriété sur le KeyboardFocusManager etc ...

0

Je ne suis pas tout à fait sûr que je comprends votre question en ce qui concerne la TreeSelectionListener et comment il se rapporte à la méthode de synchronisation stopCellEditing() appelé. Créez-vous un TreeCellEditor personnalisé? Si oui, quelques informations supplémentaires sur la configuration de cet éditeur seraient utiles. Cependant, vous avez également référencé un élément antérieur qui concernait l'édition de cellules sur un JTable, sa perte de focus sur un composant extérieur et son effet sur la cellule d'édition. J'ai pris ça comme un indice que vous souhaitez une solution similaire pour JTree ...


Comme il est indiqué, JTree ne met pas en œuvre la gestion de la propriété pour "terminateEditOnFocusLost" hors de la boîte. Cela ne signifie pas que vous pouvez le faire vous-même. En regardant le code JTable, c'est assez simple. Une classe est constituée dont le seul travail est d'identifier si le JTree a toujours le focus quand il y a un changement de focus, et sinon, il appelle stopEditing() et si cela échoue, il appelle cancelEditing(). Le voici, adapté pour un arbre:

class CellEditorRemover implements PropertyChangeListener { 
    KeyboardFocusManager focusManager; 
    public CellEditorRemover(KeyboardFocusManager fm) { 
     this.focusManager = fm; 
    } 

    public void propertyChange(PropertyChangeEvent ev) { 
     if (!tree.isEditing() || 
      tree.getClientProperty("terminateEditOnFocusLost") != Boolean.TRUE) 
     { 
      return; 
     } 

     Component c = focusManager.getPermanentFocusOwner(); 
     while (c != null) { 
      if (c == tree) { // focus remains inside the tree 
       return; 
      } else if ((c instanceof Window) 
         || (c instanceof Applet && c.getParent() == null)) 
      { 
       if (c == SwingUtilities.getRoot(tree)) { 
        if (!tree.getCellEditor().stopCellEditing()) { 
         tree.getCellEditor().cancelCellEditing(); 
        } 
       } 
       break; 
      } 
      c = c.getParent(); 
     } 
    } 
} 

Vous remarquerez que votre arbre doit être accessible d'une manière ou d'une autre à cette classe.Il y a une installation de deux appels à effectuer pour faire ce travail:

tree.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); 
KeyboardFocusManager fm = 
       KeyboardFocusManager.getCurrentKeyboardFocusManager(); 
editorRemover = new CellEditorRemover(fm); 
fm.addPropertyChangeListener("permanentFocusOwner", editorRemover); 

Cela devrait avoir l'avantage supplémentaire de faire votre JTree se comportent de la même façon que votre JTable se comporte lorsque vous appuyez sur une JButton.