5

私は問題を抱えており、誰かが何がうまくいかないのか、その理由を知っていて、提案どおりに機能させるために今見逃していることを説明してくれることを願っています。

カスタム TreeModel (「WRTreeModel」、以下を参照) に基づいて構築された JTree があります。このモデルが使用されるデータ構造は、いくつかのフィールドと、さらに以下に示す「ArrayListModel」に基づくリストを含むルート オブジェクトのビルドです。WRTreeModel を使用してツリーを構築すると、ツリーがきれいに見えます。オブジェクトに含まれるリストとフィールドを表すノードを展開および折りたたむことができます。これらのリストを展開したり折りたたんだり、その内容を確認したりできます。

ここで、リストの 1 つの子を削除したいと思います。既にわかっているように、ArrayListModel の remove メソッドを呼び出してモデルから子を削除します。WRTreeModel にその削除を認識させるには、まずその fireIntervalRemoved メソッドを呼び出す必要があります。これまでのところは問題ありません。

WRTreeModels の内部クラス ArrayModelListener では、intervalRemoved メソッドが fireTreeNodesRemoved の呼び出しを準備し、登録されているすべての TreeModelListeners (したがって、モデルに接続されたときに自動的に登録される JTree) に転送される TreeEvent を構築します。

ここで、ツリーが変更を反映し、内部および視覚的表現を更新して新しい状態を表示することを期待します。残念ながら、これはそのようには機能しないようです。何かが起こる。しかし、ノードをクリックすると、いくつかの EventHandler-Exceptions がスローされるように変更されました。明らかに、何かが本当に混乱しました。

その場でそのような質問に答えるのは簡単ではないことは承知していますが、迅速な回答をいただければ幸いです。カスタム ツリー モデル (DefaultMutableTreeNode または特定の実装ベースのクラスではなく) の使用と、JTree のイベント処理と更新がどのように機能するかを説明している Web サイトを誰かが知っていれば、それも役に立ちます。

敬具、

トーマス・アーツ


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

...

}
4

4 に答える 4

2

TreeModelListener.treeNodesRemovedノードの削除と、イベント ディスパッチ スレッドで発生する後続のイベントを実行する必要があります。

これを行うには、次を使用します。

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

これを行うと、Swing が EDT を使用して削除の途中でツリーを更新するのを防ぎ、イベントの発生により、モデルが変更されたことが JTree コントロール (リスナーを追加した) に通知されます。

于 2009-12-10T17:02:04.047 に答える
0

急いでいるので、まだあなたのコードを見ていません。あなたの説明は、すべてを正しく行っており、何が必要かを考えているかのように聞こえます。

あなたが考えていないかもしれない何かについての私の推測: このツリーモデルの変更はイベントディスパッチスレッド (別名 Swing ワーカースレッド) で起こっていますか? 変更が別のスレッドからのものである場合、適切に処理されない可能性があります。

もちろん、暗闇の中で突き刺すだけです。

于 2009-12-10T13:54:19.417 に答える
0

intervalRemoved に off-by-one バグがあるようです。

インデックス配列の最後の値を初期化していません。0 に自動初期化されます。

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

代わりに「i <= e.getIndex1()」を試してください:

for (int i = e.getIndex0(); i <= e.getIndex1(); i++) {
    indices[i - e.getIndex0()] = i;
}
于 2009-12-10T14:31:00.500 に答える
0

メソッド名はですので、以下削除し fireIntervalRemovedて呼び出してみてください。

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

それは私が行ってきた方法であり、常に機能していました(おそらくいくつかのチェックが追加されました)。
(何かを見逃していたらごめんなさい、コードを分析/テストする時間がありませんでした...)

于 2009-12-10T14:53:27.633 に答える