Я столкнулся с той же «проблемой»: вызов treeNodesInserted()
не заставил мой JTree
обновить его содержимое.
Но проблема была в другом месте: я использовал неправильный конструктор для TreeModelEvent
. Я думал, что могу создать TreeModelEvent
для treeNodesInserted()
так:
//-- Wrong!!
TreePath path_to_inserted_item = /*....*/ ;
TreeModelEvent tme = new TreeModelEvent(my_source, path_to_inserted_item);
Это не работает.
Как указано в TreeModelEvent
документах , этот конструктор необходим только для treeStructureChanged()
. Но для treeNodesInserted()
, treeNodesRemoved()
, treeNodesChanged()
мы должны использовать другой конструктор:
TreePath path_to_parent_of_inserted_items = /*....*/ ;
int[] indices_of_inserted_items = /*....*/ ;
Object[] inserted_items = /*....*/ ;
TreeModelEvent tme = new TreeModelEvent(
my_source,
path_to_parent_of_inserted_items,
indices_of_inserted_items,
inserted_items
);
Этот код работает, и JTree
правильно обновляет его содержимое.
UPD: На самом деле, документам неясно, как использовать эти TreeModelEvent
с, особенно с JTree
, поэтому я хочу рассказать о некоторых вопросах, которые возникли у меня, когда я пытался выяснить как бороться со всем этим.
Во-первых, как отметил Паралифе в своем комментарии, случаи, когда узлы вставляются / изменяются / удаляются или когда изменяется древовидная структура, не являются ортогональными. Таким образом,
Вопрос № 1: когда мы должны использовать treeNodesInserted()
/ Changed()
/ Removed()
, а когда treeStructureChanged()
?
Ответ: treeNodesInserted()
/ Changed()
/ Removed()
можно использовать, если только все затронутые узлы имеют одного и того же родителя. В противном случае вы можете сделать несколько вызовов этих методов или просто вызвать treeStructureChanged()
один раз (и передать ему корневой узел затронутых узлов). Итак, treeStructureChanged()
является своего рода универсальным способом, в то время как treeNodesInserted()
/ Changed()
/ Removed()
более конкретны.
Вопрос № 2: Поскольку treeStructureChanged()
является универсальным способом, зачем мне иметь дело с этими treeNodesInserted()
/ Changed()
/ Removed()
? Просто позвонить на treeStructureChanged()
кажется проще.
Ответ: Если вы используете JTree
для отображения содержимого вашего дерева, то следующая вещь может быть сюрпризом для вас (как и для меня): когда вы звоните treeStructureChanged()
, тогда JTree
не сохраняет состояние расширения подузлов! Рассмотрим пример, вот содержимое нашего JTree
сейчас:
[A]
|-[B]
|-[C]
| |-[E]
| | |-[G]
| | |-[H]
| |-[F]
| |-[I]
| |-[J]
| |-[K]
|-[D]
Затем вы вносите некоторые изменения в C
(скажем, переименовываете в C2
), и для этого вы звоните treeStructureChanged()
:
myTreeModel.treeStructureChanged(
new TreeModelEvent(
this,
new Object[] { myNodeA, myNodeC } // Path to changed node
)
);
Тогда узлы E
и F
будут свернуты! И ваш JTree
будет выглядеть так:
[A]
|-[B]
|-[C2]
| +-[E]
| +-[F]
|-[D]
Чтобы избежать этого, вы должны использовать treeNodesChanged()
, вот так:
myTreeModel.treeNodesChanged(
new TreeModelEvent(
this,
new Object[] { myNodeA }, // Path to the _parent_ of changed item
new int[] { 1 }, // Indexes of changed nodes
new Object[] { myNodeC }, // Objects represents changed nodes
// (Note: old ones!!!
// I.e. not "C2", but "C",
// in this example)
)
);
Тогда состояние расширения будет сохранено.
Надеюсь, этот пост кому-нибудь пригодится.