Почему выбор узла не работает должным образом после перезагрузки TreeModel?
У меня есть приложение Swing, которое использует JTree
, Я хочу, чтобы некоторые узлы дерева были скрыты, поэтому я реализовал два DefaultTreeModel
s, один с каждым узлом и фильтрованный только с теми, которые должны отображаться. Последний устанавливается как актуальная модель.
В некоторых моментах я должен изменить отфильтрованные узлы, и когда я это сделаю, элементы в дереве обновляются должным образом, но их поведение является неправильным. Узлы не подсвечиваются, когда они выбраны (даже если они действительно выбраны), и пользователь больше не может дважды щелкнуть, чтобы развернуть узел, он должен нажать маленькую кнопку "+".
Ниже приведено обобщение моего кода, два метода из моего пользовательского класса, который расширяет JTree
,
updateFilter
вызывается, когда фильтр должен быть обновлен.populateFilteredNode
рекурсивно заполняет корневой узел моей отфильтрованной модели. Для простоты, filteredRoot
переменная члена класса (типа DefaultMutableTreeNode
) и является корнем отфильтрованной модели. fullModel
а также filteredModel
имеют тип DefaultTreeModel
public void updateFilter() {
// Get current expansion state
ArrayList<Integer> expansionState = getExpansionState();
DefaultMutableTreeNode fullModelRoot = fullModel.getRoot();
// Remove existing nodes in the filtered model
while(filteredRoot.getChildCount() > 0) {
filteredModel.removeNodeFromParent(filteredRoot.getFirstChild());
}
populateFilteredNode(fullModelRoot, filteredRoot);
// Repaint tree and restore expansion state
repaint();
setExpansionState(expansionState);
}
private void populateFilteredNode(DefaultMutableTreeNode fullNode, DefaultMutableTreeNode filteredNode) {
int index = 0;
for(int n = 0; n < fullNode.getChildCount(); n++) {
DefaultMutableTreeNode fullChildNode = fullNode.getChildAt(n);
// Show the item and its children if one of many cases is true
if(shouldShowItem(fullChildNode.getItem())) {
DefaultMutableTreeNode filteredChildNode = fullChildNode.clone();
filteredModel.insertNodeInto(filteredChildNode, filteredNode, index++);
populateFilteredNode(fullChildNode, filteredChildNode);
}
}
}
Если кто-то имеет подобный опыт или знает, почему выбранный узел не будет выделен, пожалуйста, дайте мне знать. Или, если есть лучший способ выполнить фильтрацию. Или, если больше кода поможет дать ответ.
1 ответ
Я нашел кое-что, что работает для моего случая, хотя это быстро и грязно, и я не обязательно понимаю, почему это работает. Этот 12-летний пост на "Ранчо кодов" каким-то образом направил меня в правильном направлении. Я просто выкладываю это здесь на тот случай, если у кого-то возникнут похожие проблемы, и это может помочь.
Я сохраняю путь выбора перед внесением каких-либо изменений в модель таблицы, а затем вызываю эту новую функцию findNewSelectionPath
после внесения изменений. Ниже приведена обобщенная версия функции (я использую несколько пользовательских классов, поэтому я приложил все усилия, чтобы она выглядела как универсальная).
private TreePath findNewSelectionPath(TreePath oldSelectionPath) {
TreePath newSelectionPath = null;
if(oldSelectionPath != null) {
Object[] oldPathComponents = oldSelectionPath.getPath();
Object[] newPathComponents = new Object[oldPathComponents.length];
DefaultMutableTreeNode node = (DefaultMutableTreeNode) filteredModel.getRoot();
// Set the root
if(oldPathComponents[0].equals(node)) {
newPathComponents[0] = node;
}
// Set the rest of the path components
for(int n = 1; n < oldPathComponents.length; n++) {
for(int k = 0; k < node.getChildCount(); k++) {
if(oldPathComponents[n].equals(node.getChildAt(k))) {
newPathComponents[n] = node.getChildAt(k);
node = node.getChildAt(k);
break;
}
}
}
// Make sure that the last path component exists
if(newPathComponents[newPathComponents.length - 1] != null) {
newSelectionPath = new TreePath(newPathComponents);
}
}
return newSelectionPath;
}