我有一个问题和希望,有人知道出了什么问题以及为什么并且能够给我解释我现在错过的东西,以使该东西按照建议工作.
我有一个基于自定义TreeModel的JTree("WRTreeModel",见下文).该模型应用于的数据结构是包含一些字段的根对象的构建,以及由下面所示的"ArrayListModel"支持的列表.当我使用WRTreeModel构建它时,树看起来很好.我能够展开和折叠表示对象中包含的列表和字段的节点.我可以展开和折叠这些列表并查看其内容等等.
现在我想删除其中一个列表的子节点 - 正如我已经知道的那样 - 通过从调用ArrayListModel的remove方法的模型中删除它来实现它.为了使WRTreeModel知道删除,首先要调用它的fireIntervalRemoved方法被调用,到目前为止一直这么好.
在WRTreeModels内部类ArrayModelListener中,intervalRemoved方法准备fireTreeNodesRemoved的调用,然后构建一个TreeEvent,该TreeEvent被转发到所有已注册的TreeModelListeners(因此当它连接到模型时,它自动注册自己的JTree).
现在我希望树能够反映变化并更新它的内部和视觉表示以显示新状态.不幸的是,这似乎并没有这样做.有事情发生.但是,当我点击节点时,我刚刚更改了一些EventHandler-Exceptions被抛出.显然有些事情真的很混乱.
我知道在飞行中回答这样的问题并不容易,但我真的很感激快速回答.如果有人知道网站解释使用自定义树模型(不是在DefaultMutableTreeNode或任何给定的基于实现的类)以及如何处理和更新JTree的工作,那么它也会有所帮助.
最诚挚的问候,
托马斯艺术
public class ArrayListModel<E> extends ArrayList<E> implements ListModel {
...
public E remove(int index) {
fireIntervalRemoved(index, index);
E removedElement = super.remove(index);
return removedElement;
}
...
}
Run Code Online (Sandbox Code Playgroud)
public class WRTreeModel extends LogAndMark implements TreeModel {
class ArrayModelListener implements ListDataListener {
...
@Override
public void intervalRemoved(ListDataEvent e) {
int[] indices = new int[e.getIndex1() - e.getIndex0() + 1];
for (int i = e.getIndex0(); i < e.getIndex1(); i++)
indices[i - e.getIndex0()] = i;
fireTreeNodesRemoved(e.getSource(), getPathToRoot(e.getSource()), indices, ((ArrayListModel<?>)e.getSource()).subList(e.getIndex0(), e.getIndex1()+1).toArray());
}
...
}
public Object[] getPathToRoot(Object child) {
ArrayList<Object> ret = new ArrayList<Object>();
if (child == null)
return ret.toArray();
ret.add(root);
if (child == root)
return ret.toArray();
int childType = 0;
if (child instanceof List<?> && ((List) child).get(0) instanceof Einleitungsstelle) {
childType = 1;
}
if (child instanceof Einleitungsstelle) {
childType = 2;
}
if (child instanceof List<?> && ((List) child).get(0) instanceof Messstelle) {
childType = 3;
}
if (child instanceof Messstelle) {
childType = 4;
}
if (child instanceof List<?> && ((List) child).get(0) instanceof Ueberwachungswert) {
childType = 5;
}
if (child instanceof Ueberwachungswert) {
childType = 6;
}
if (child instanceof List<?> && ((List) child).get(0) instanceof Selbstueberwachungswert) {
childType = 7;
}
if (child instanceof Selbstueberwachungswert) {
childType = 8;
}
switch (childType) {
// List of ESTs
case 1: {
ret.add(child);
break;
}
// EST
case 2: {
List<Einleitungsstelle> listOfEST = ((Wasserrecht) (root)).getListOfEST();
ret.add(listOfEST);
ret.add(child);
break;
}
// List of MSTs
case 3: {
List<Einleitungsstelle> listOfEST = ((Wasserrecht) (root)).getListOfEST();
ret.add(listOfEST);
// Find the EST containing the List of MSTs the child referes to
for (Einleitungsstelle einleitungsstelle : listOfEST) {
if (child == einleitungsstelle.getListOfMST()) {
ret.add(einleitungsstelle);
break;
}
}
ret.add(child);
break;
}
// MST
case 4: {
List<Einleitungsstelle> listOfEST = ((Wasserrecht) (root)).getListOfEST();
ret.add(listOfEST);
// Find the EST containing the List of MSTs the child referes to
for (Einleitungsstelle einleitungsstelle : listOfEST) {
if (child == einleitungsstelle.getListOfMST()) {
ret.add(einleitungsstelle.getListOfMST());
break;
}
}
ret.add(child);
break;
}
// List of UEWs
case 5: {
List<Einleitungsstelle> listOfEST = ((Wasserrecht) (root)).getListOfEST();
ret.add(listOfEST);
// Find the EST containing the List of MSTs the child referes to
for (Einleitungsstelle einleitungsstelle : listOfEST) {
ArrayListModel<Messstelle> listOfMST = einleitungsstelle.getListOfMST();
if (child == listOfMST) {
ret.add(listOfMST);
for (Messstelle messstelle : listOfMST) {
if (child == messstelle.getListOfUEW()) {
ret.add(messstelle.getListOfUEW());
break;
}
}
break;
}
}
break;
}
// UEW
case 6: {
List<Einleitungsstelle> listOfEST = ((Wasserrecht) (root)).getListOfEST();
ret.add(listOfEST);
// Find the EST containing the List of MSTs the child referes to
for (Einleitungsstelle einleitungsstelle : listOfEST) {
ArrayListModel<Messstelle> listOfMST = einleitungsstelle.getListOfMST();
if (child == listOfMST) {
ret.add(listOfMST);
for (Messstelle messstelle : listOfMST) {
if (child == messstelle.getListOfUEW()) {
ret.add(messstelle.getListOfUEW());
break;
}
}
break;
}
}
ret.add(child);
break;
}
// List of SUEWs
case 7: {
List<Einleitungsstelle> listOfEST = ((Wasserrecht) (root)).getListOfEST();
ret.add(listOfEST);
// Find the EST containing the List of MSTs the child referes to
for (Einleitungsstelle einleitungsstelle : listOfEST) {
ArrayListModel<Messstelle> listOfMST = einleitungsstelle.getListOfMST();
if (child == listOfMST) {
ret.add(listOfMST);
for (Messstelle messstelle : listOfMST) {
if (child == messstelle.getListOfSUEW()) {
ret.add(messstelle.getListOfSUEW());
break;
}
}
break;
}
}
break;
}
// SUEW
case 8: {
List<Einleitungsstelle> listOfEST = ((Wasserrecht) (root)).getListOfEST();
ret.add(listOfEST);
// Find the EST containing the List of MSTs the child referes to
for (Einleitungsstelle einleitungsstelle : listOfEST) {
ArrayListModel<Messstelle> listOfMST = einleitungsstelle.getListOfMST();
if (child == listOfMST) {
ret.add(listOfMST);
for (Messstelle messstelle : listOfMST) {
if (child == messstelle.getListOfSUEW()) {
ret.add(messstelle.getListOfSUEW());
break;
}
}
break;
}
}
ret.add(child);
break;
}
default:
ret = null;
}
return ret.toArray();
}
}
...
protected void fireTreeNodesRemoved(Object changed, Object path[], int childIndecies[], Object children[]) {
TreeModelEvent event = new TreeModelEvent(this, path, childIndecies, children);
synchronized (listeners) {
for (Enumeration e = listeners.elements(); e.hasMoreElements();) {
TreeModelListener tml = (TreeModelListener) e.nextElement();
tml.treeNodesRemoved(event);
}
}
}
...
}
Run Code Online (Sandbox Code Playgroud)
TreeModelListener.treeNodesRemoved您需要在事件调度线程上执行节点删除和后续事件触发。
要执行此操作,请使用:
SwingUtilities.invokeLater(
new Runnable()
{
public void run()
{
//Delete and event firing logic goes here.
...
}
}
);
Run Code Online (Sandbox Code Playgroud)
这样做可以防止 Swing 在删除过程中使用 EDT 更新树,并且事件触发会告诉 JTree 控件(已添加侦听器)模型已更改。