Comment puis-je actualiser un JTree après avoir ajouté des nœuds au modèle sous-jacent?
Tout d'abord, permettez-moi de dire que je n'utilise pas le DefaultTreeModel. Je mets en œuvre mon propre TreeModel, donc je ne peux pas utiliser le DefaultXXX choses. Le problème est: est-ce Par le biais de certains addStuff() sont des méthodes qui mon modèle définit-je ajouter des nœuds de la structure de données sous-jacente. Je puis informer les auditeurs en appelant treeNodesChanged() à l'intérieur de la addStuff() fonction (je Sais qu'il y a treeNodesInserted méthodes, mais c'est la même chose. Il vient informe les auditeurs avec une méthode différente). Maintenant, l'un des auditeurs est une classe statique dans mon formulaire principal et ce auditeur peut dire le JTree, qui est également contenue dans mon formulaire principal, pour actualiser lui-même. Comment dois-je dire à la JTree "recharger" de certaines ou de l'ensemble de ses nœuds du modèle?
Mise à JOUR:
Trouvé ce question que, bien que pas exactement le même, il donne la réponse que je veux.
Mise à JOUR 2:
Mon problème n'était pas la façon d'informer le spectateur (JTree), mais plutôt dans ce qui doit être la jtree être rechargé après la notification du modèle.
Tout d'abord permettez-moi de dire que le seul moyen que je connaisse pour actualiser un arbre afin de refléter les changements sous-jacents, c'est d'appeler le updateUI(), ou de réutiliser le setModel() la méthode. Essentiellement, mon problème est le suivant:
Supposons que le TreeModelListener a simplement été informé (par l'entremise de la TreeModelListener API) qu'un changement a eu lieu dans le modèle. Ok, et maintenant?
J'ai ce problème parce que le JTree ne pas mettre en œuvre TreeModelListener. Afin que l'auditeur, dans ma situation, est le JTree du conteneur, ou d'une classe interne la mise en œuvre de l'Auditeur, vivant sous le même contenant que les Jtree.
Supposons donc que je suis un TreeModelListener mise en œuvre, mène une vie heureuse dans un JForm avec mon frère JTree. Soudain, ma méthode treeNodesInserted(TreeModelEvent evt) est appelée. Que dois-je faire maintenant? Si je l'appelle Jtree.updateUI() à l'intérieur de moi, puis le modèle auditeurs Liste jette ConcurrentModification Exception. Puis-je appeler quelque chose d'autre que updateUI?
J'ai essayé un certain nombre de choses, mais seulement updateUI actualisé le JTree. Donc je l'ai fait à l'extérieur de l'auditeur. À partir de la JForm, je viens d'appeler le modèle de la méthode qui modifie la undrlying structure, puis-je appeler updateUI. Pas de TreeModelListener s'habitue.
UPDATE3:
J'ai trouvé qu'il n'y sont implicites TreeModelListeners enregistré. Dans mon modèle de addTreeModelListener(TreeModelListener auditeur) j'ai mis de la mise en œuvre d'un système de débogage.ligne:
System.out.println("listener added: " + listener.getClass().getCanonicalName());
et j'ai vu cette sortie de débogage juste quand j'ai exécuté jTree.setModel(model):
auditeur ajouté: javax.swing.JTree.TreeModelHandler
auditeur ajouté: javax.swing.plaf.de base.BasicTreeUI.Gestionnaire
La ConcurrentModificationException est causée en raison d'un appel à jtree.updateUI() re registres de l'auditeur (uniquement le plaf, pas les deux) donc il est jeté quand je l'appelle updateUI à l'intérieur d'un auditeur de la notification de la boucle.
La seule manière d'actualiser l'arbre est de le faire à l'extérieur de TreeModelListener. Des commentaires ou des idées pour une meilleure solution? Ai-je raté quelque chose?
source d'informationauteur Paralife
Vous devez vous connecter pour publier un commentaire.
J'ai affronté le même "problème": l'appel de
treeNodesInserted()
n'est pas la cause de monJTree
de mettre à jour son contenu.Mais le problème était dans un autre endroit: j'ai utilisé le mauvais constructeur de
TreeModelEvent
. J'ai pensé que je puisse créerTreeModelEvent
pourtreeNodesInserted()
comme ça:Cela ne fonctionne pas.
Comme indiqué dans
TreeModelEvent
docsce constructeur n'est nécessaire pourtreeStructureChanged()
. Mais pourtreeNodesInserted()
treeNodesRemoved()
treeNodesChanged()
nous devrions utiliser un autre constructeur:Ce code fonctionne, et
JTree
les mises à jour de son contenu correctement.UPD: en Fait, les docs ne sont pas claires sur l'utilisation de ces
TreeModelEvent
s, et surtout avecJTree
donc, je veux parler de certaines des questions qui m'est venue quand j'ai essayé de comprendre comment faire face à tout ce genre de choses.Tout d'abord, comme Paralife noté son commentaire, les cas où l'insertion des nœuds/modifiés/supprimés, ou lorsque la structure de l'arbre est modifiée, ne sont pas orthogonaux. Donc,
Question #1: quand doit-on utiliser
treeNodesInserted()
/Changed()
/Removed()
et quandtreeStructureChanged()
?Réponse:
treeNodesInserted()
/Changed()
/Removed()
peut être utilisé si seulement tous les nœuds touchés ont le même parent. Sinon, vous pouvez faire plusieurs appels à ces méthodes, ou tout simplement appelertreeStructureChanged()
une fois (et passer le nœud racine de nœuds touchés). Donc,treeStructureChanged()
est une sorte de manière universelle, tandis quetreeNodesInserted()
/Changed()
/Removed()
sont plus spécifiques.Question #2: autant Que
treeStructureChanged()
est un moyen universel, pourquoi ai-je besoin pour faire face à cestreeNodesInserted()
/Changed()
/Removed()
? Appelez simplement àtreeStructureChanged()
semble plus facile.Réponse: Si vous utilisez
JTree
pour afficher le contenu de votre arbre, puis, le lendemain c'est peut-être un surprize pour vous (comme pour moi) : lorsque vous appeleztreeStructureChanged()
puisJTree
permet de ne pas garder d'étendre l'état de sous-nœuds! Prenons l'exemple, voici le contenu de notreJTree
maintenant:Ensuite vous apporter quelques modifications à
C
(par exemple, renommerC2
), et que vous appeleztreeStructureChanged()
:Ensuite, les nœuds
E
etF
sera effondré! Et votreJTree
ressemblera à cela:Pour éviter cela, vous devez utiliser
treeNodesChanged()
comme ça:Ensuite, l'expansion de l'etat sera maintenue.
J'espère que ce post sera utile à quelqu'un.
J'ai toujours trouvé le TreeModel un peu déroutant. Je suis d'accord avec la déclaration ci-dessus que le modèle doit notifier l'affichage lorsqu'un changement est effectué de sorte que la vue peut se repeindre. Cependant, cela ne semble pas être le cas lors de l'utilisation de la DefaultTreeModel. Je trouve que vous devez invoquer le reload() la méthode après la mise à jour du modèle. Quelque chose comme:
J'ai aussi trouvé la mise en œuvre de TreeModel un peu déroutant lorsque l'arbre se composent de plus que juste des Dossiers(la racine) et de Fichiers(enfant), j'ai donc utilisé la DefaultTreeModel. Cela fonctionne pour moi. La méthode crée ou actualise le JTree. Espérons que cette aide.
Votre TreeModel est censé feu TreeModelEvents quand elle change, et le JTree observe votre modèle si un TreeModelListener pour actualiser lui-même lors de vos changements de modèle.
Donc, si vous mettre en œuvre les TreeModelListener soutenir correctementvous n'avez pas besoin d'observer le modèle et d'en informer le JTree, comme elle l'a déjà fait lui-même. À partir d'un MVC perspecive, le JTree est votre point de Vue/Contrôleur, et le TreeModel est votre Modèle (ou plutôt: modèle de carte), ce qui est observable.
Vous pouvez essayer de forcer le JTree de mettre à jour son état visuel en appelant repaint(), mais je vous recommande de ne pas le faire car cela n'est pas garanti pour fonctionner.
Lorsque vous n'êtes pas sûr de comment faire une fine granular notification à un TreeModelListener, utilisez TreeModelListener.treeStructureChanged(..) pour notifier un 'modèle' de mise à jour (attention: peut causer des sélections et le nœud de l'expansion des états d'être perdu).
Hier, j'ai struggeled autour pour résoudre le même problème. L'exigence était d'insérer et de supprimer des nœuds à la volée, sans réduction de l'étendu des nœuds de l'arborescence. J'ai parcouru le web et trouvé un tas de solutions possibles, jusqu'à ce que je suis tombé sur ce fil. Puis j'ai appliqué la réponse de "Dimitri Frank" avec le
TreeModelEvent
. J'ai été un peu confus, pourquoi c'est un gros problème pour insérer ou supprimer un nœud simple et de laisser le reste de laJTree
intacte!Enfin la plaine de vanille exemples de java2s m'a aidé à trouver le probablement la solution la plus simple. (Ni un appel comme:
nodeStructureChanged
,nodeChanged
,nodesWereRemoved
,nodesWereInserted
, etc. ni uneTreeModelEvent
comme suggéré par "Dimitri Frank" a été requis.)Voici ma solution:
Faire simple 😉
dernière mise à JOUR:: Les étapes suivantes pour résoudre le problème,(mais voir la accepté de répondre à une meilleure solution et une profonde explication du problème):Trouvé le problème et résolu
treeNodesInserted()
il ne fonctionne pas (JTree pas mis à jour). Mais Il fonctionne avec l'appel detreeStructureChanged()
.Apparemment, l'implicite, les auditeurs sont à l'interne de l'actualisation de l'arbre de la façon dont je le veux, mais seulement dans leur
treeStructureChanged()
méthode de la mise en œuvre. Il serait bon pour JTree à fournir cet "algorithme" comme une fonction afin de pouvoir être appelé manuellement.Par exemple:Jtree Actualiser de façon dynamique
Il semble être possible de réinitialiser l'ensemble de l'arbre en fixant le modèle à null:
par exemple,
Arbre de mise à jour fonctionne pour moi
kr Achim