Swing问题/ JTree /自定义树模型 [英] Swing question / JTree / custom tree model

查看:157
本文介绍了Swing问题/ JTree /自定义树模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题和希望,有人知道出了什么问题,为什么和能够给我解释我现在错过的东西,使这个事情按照建议工作。



我有一个基于自定义TreeModel(WRTreeModel,见下文)的JTree。
该模型的数据结构应该用于构建一个根对象,该对象包含一些字段,还有一个由ArrayListModel支持的列表,如下所示。
当我使用WRTreeModel构建它时,树看起来不错。我可以展开和折叠表示对象中包含的列表和字段的节点。
我可以扩展和折叠这些列表,并查看其内容等等。



现在我想删除其中一个列表的子项,我已经知道 - 通过从调用ArrayListModel的remove方法的模型中删除它来实现。
为了使WRTreeModel知道该删除,首先是调用它的fireIntervalRemoved方法被调用,到目前为止这么好。



在WRTreeModels内部类中ArrayModelListener intervalRemoved方法准备了fireTreeNodesRemoved的调用,然后构建一个TreeEvent,该事件被转发到所有已注册的
TreeModelListeners(因此JTree在连接到模型时注册自身)。



现在我希望树反映变化,并更新它的内部和视觉表示以显示新的状态。
不幸的是,这似乎不会这样工作。有事情发生。但是当我点击节点时,我刚刚改变了一些EventHandler异常被抛出。
显然有些东西真的很困惑。



我知道这样一个问题在飞行中是不容易的,但我真的很感激一个快速的答案。
如果有人知道使用自定义树模型(不在DefaultMutableTreeNode或任何给定的基于实现的类)的网站以及Jtree的
事件处理和更新的工作方式,这也将是有帮助的。 / p>

有最好的问候,



Thomas Arts






  public class ArrayListModel< E>扩展ArrayList< E>实现ListModel {

...

public E remove(int index){
fireIntervalRemoved(index,index);
E removedElement = super.remove(index);
return removedElement;
}

...

}






  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]; (int i = e.getIndex0(); i< e.getIndex1(); i ++)
索引[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)instancein 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){
// EST的列表
案例1:{
ret.add(child);
break;
}
// EST
案例2:{
列表< Einleitungsstelle> listOfEST =((Wasserrecht)(root))。getListOfEST();
ret.add(listOfEST);
ret.add(child);
break;
}
// MST列表
案例3:{
列表< Einleitungsstelle> listOfEST =((Wasserrecht)(root))。getListOfEST();
ret.add(listOfEST);
//找到包含孩子参考的MST列表的EST(Einleitungsstelle einleitungsstelle:listOfEST){
if(child == einleitungsstelle.getListOfMST()){
ret.add(einleitungsstelle);
break;
}
}
ret.add(child);
break;
}
// MST
案例4:{
列表< Einleitungsstelle> listOfEST =((Wasserrecht)(root))。getListOfEST();
ret.add(listOfEST);
//找到包含孩子参考的MST列表的EST(Einleitungsstelle einleitungsstelle:listOfEST){
if(child == einleitungsstelle.getListOfMST()){
ret.add(einleitungsstelle.getListOfMST());
break;
}
}
ret.add(child);
break;
}
// UEWs列表
案例5:{
列表< Einleitungsstelle> listOfEST =((Wasserrecht)(root))。getListOfEST();
ret.add(listOfEST);
//找到包含孩子参考的MST列表的EST($ E
)(Einleitungsstelle einleitungsstelle:listOfEST){
ArrayListModel< Messstelle> listOfMST = einleitungsstelle.getListOfMST();
if(child == listOfMST){
ret.add(listOfMST);
(Messstelle messstelle:listOfMST){
if(child == messstelle.getListOfUEW()){
ret.add(messstelle.getListOfUEW());
break;
}
}
break;
}
}
break;
}
// UEW
案例6:{
列表< Einleitungsstelle> listOfEST =((Wasserrecht)(root))。getListOfEST();
ret.add(listOfEST);
//找到包含孩子参考的MST列表的EST($ E
)(Einleitungsstelle einleitungsstelle:listOfEST){
ArrayListModel< Messstelle> listOfMST = einleitungsstelle.getListOfMST();
if(child == listOfMST){
ret.add(listOfMST);
(Messstelle messstelle:listOfMST){
if(child == messstelle.getListOfUEW()){
ret.add(messstelle.getListOfUEW());
break;
}
}
break;
}
}
ret.add(child);
break;
}
//列表SUEWs
案例7:{
列表< Einleitungsstelle> listOfEST =((Wasserrecht)(root))。getListOfEST();
ret.add(listOfEST);
//找到包含孩子参考的MST列表的EST($ E
)(Einleitungsstelle einleitungsstelle:listOfEST){
ArrayListModel< Messstelle> listOfMST = einleitungsstelle.getListOfMST();
if(child == listOfMST){
ret.add(listOfMST);
(Messstelle messstelle:listOfMST){
if(child == messstelle.getListOfSUEW()){
ret.add(messstelle.getListOfSUEW());
break;
}
}
break;
}
}
break;
}
// SUEW
案例8:{
列表< Einleitungsstelle> listOfEST =((Wasserrecht)(root))。getListOfEST();
ret.add(listOfEST);
//找到包含孩子参考的MST列表的EST($ E
)(Einleitungsstelle einleitungsstelle:listOfEST){
ArrayListModel< Messstelle> listOfMST = einleitungsstelle.getListOfMST();
if(child == listOfMST){
ret.add(listOfMST);
(Messstelle messstelle:listOfMST){
if(child == messstelle.getListOfSUEW()){
ret.add(messstelle.getListOfSUEW());
break;
}
}
break;
}
}
ret.add(child);
break;
}
默认值:
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);
}
}
}

...

}


解决方案

您需要执行节点删除和后续的 TreeModelListener.treeNodesRemoved 事件发送线程上的事件触发。



要执行此操作:

  SwingUtilities.invokeLater(
new Runnable()
{
public void run()
{
//删除和事件触发逻辑到这里
...
}
}
);

这样做可以防止Swing使用EDT更新删除中间的树,并触发事件告诉JTree控件(其添加了监听器)模型已更改。


I'm having a problem and hope, someone knows what's going wrong and why and is able to give me the explanation of what I'm missing out right now to make that thing work as suggested.

I have a JTree which is build upon a custom TreeModel ("WRTreeModel", see below). The data structure this model shall be used for is build of an root object which contains some fields and furthermore a list which is backed by the "ArrayListModel" shown below. The tree looks fine when I build it using the WRTreeModel. I'm able to expand and collapse the nodes which represent the lists and fields contained in the objects. I can expand and collapse these lists and see their contents as well and so on.

Now I want to remove a child of one of the lists and - as I already know - do it by removing it from the model calling the remove method of the ArrayListModel. To make the WRTreeModel aware of that remove, the first thing is to call its fireIntervalRemoved method is called, so far so good.

In the WRTreeModels inner class ArrayModelListener the intervalRemoved method prepares the call of fireTreeNodesRemoved which then builds a TreeEvent which is forwarded to all registered TreeModelListeners (and therefore the JTree which registers itself automaticall when it's connected to the model).

Now I would expect that the tree reflects the change and updates it's internal and visual representation to show the new state. Unfortunately this doesn't seem to work that way. Something happens. But when I click on the node I just have changed some EventHandler-Exceptions are thrown. Obviously something got really confused.

I know it's not easy to answer such a question on the fly but I would really appreciate a fast answer. It would also be of help, if someone knew websites explaining the use of custom tree models (not on DefaultMutableTreeNode or any given implementation based class) and how the event handling and updating of the JTree works.

With best regards,

Thomas Arts


public class ArrayListModel<E> extends ArrayList<E> implements ListModel {

...

public E remove(int index) {
    fireIntervalRemoved(index, index);
    E removedElement = super.remove(index);
    return removedElement;
  }

...

}


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);
      }
      }
    }

...

}

解决方案

You need to perform the node delete and the subsequent TreeModelListener.treeNodesRemoved event firing on the Event Dispatch Thread.

To do this use:

SwingUtilities.invokeLater(
  new Runnable() 
  {
    public void run() 
    {
      //Delete and event firing logic goes here.
      ...
    }
  }
);

Doing this prevents Swing using the EDT to update the tree in the middle of your delete and the event firing tells the JTree control (which has added listeners) that the model has changed.

这篇关于Swing问题/ JTree /自定义树模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆