- PR -

どうしても理解できないことがあります

1
投稿者投稿内容
isseki
大ベテラン
会議室デビュー日: 2001/11/05
投稿数: 107
投稿日時: 2003-05-07 13:57
いつもお世話になります。

OS: WIN98
J2SDK1.4.1

import javax.swing.tree.DefaultMutableTreeNode;

cNode、xNode ともDefaultMutableTreeNodeを継承したclassのインスタンスです。
具体にこのようなclassです:

=========================================
public class Node extends DefaultMutableTreeNode implements Comparable{

・・・・・・・・・・・
}

cNode = new Node();
xNode = new Node();

=========================================
ところが、 xNode.add(new DefaultMutableTreeNode());
の実行はいつも無事ですが、

  xNode.add(cNode);
を実行する時いつも下のようなエラーが出ます。
==============================================================
java.lang.IllegalArgumentException: argument is not a child
at javax.swing.tree.DefaultMutableTreeNode.remove(DefaultMutableTreeNode.java:366)
at javax.swing.tree.DefaultMutableTreeNode.insert(DefaultMutableTreeNode.java:171)
at javax.swing.tree.DefaultMutableTreeNode.add(DefaultMutableTreeNode.java:394)
at ReasoningEngine.doNilsson(ReasoningEngine.java:121)
at ReasoningEngine.run(ReasoningEngine.java:74)
at Agent.main(Agent.java:37)
Exception in thread "main"
==============================================================

"argument is not a child....."
本当の意味は分かっていないと思いますが、
恐らく「cNode is not a child」を意味するのでしょうね、
そうしたら、なんで
new DefaultMutableTreeNode()がchildになっているのでしょうか。

どなたかヒントでもいただければ幸いです
raccoon
ベテラン
会議室デビュー日: 2002/12/18
投稿数: 58
投稿日時: 2003-05-07 22:24
ども。raccoonです。

# わたしも意味をしっかり理解しているわけではありませんが,
# 「こんなかなぁ」という推測でコメントします。

スタックトレースからは,add() -> insert() -> remove()の順で呼ばれてますよね。
DefaultMutableTreeNodeのソースを見ると,(newChild.getParent() == null)の時は
insert()からremove()は呼ばないようになっています。

つまり,「new DefaultMutableTreeNode()がchildだ」と認識されたわけではなく,
parent==nullだから成功した,ということでしょう。
たいていの場合はparent!=nullでも成功するはずですが,
どこかで親子関係がおかしくなると,この手の例外が出るようです。

cNode = new Node();
から
xNode.add(cNode);
までの間にcNode.setParent()を呼んでいたりしませんか?
あるいは自力でchildrenいじったりとか?

# わたしの環境はWin2000 + J2SDK 1.4.0ですが,たぶん同じだと思います。

isseki
大ベテラン
会議室デビュー日: 2001/11/05
投稿数: 107
投稿日時: 2003-05-11 14:41
raccoon様
こんにちわ
ご指導ありがとうございます。
(これに対して私のレスがいかにも遅くて、大変申し訳ございません m(__)m)

まったくご推測のとおりです。
raccoonさんに敬意を表したいですね。

質問の後、私もさらに時間をかけて調べました。
分かったのは
DefaultMutableTreeNode#add(DefaultMutableTreeNode node)
というメッソドはindexを設定できない以外、まったく
DefaultMutableTreeNode#insert(DefaultMutableTreeNode node, index in)
と同じようです。

insertは高度な機能を持っており、node1をnode2の子にする時まずnode1がこれまでに
親がなかったかどうかを調べ、あれば、元の親(!)の子リストからnode1を削除した後、
初めてnode2の子として以下のように二つの作業を行います。

#1> node2(親)側: node1をnode2の子リストに登録する
#2> node1(子)側: node2をnode1の親(唯一)として登録する


ところが、ご指摘されたような
DefaultMutableTreeNode#setParent(DefaultMutableTreeNode parent)
というメソッドもあります。
こっちはちょっと「粗末」なもんで、子のほうだけが親を設定し、
設定された親のほうはこの子を認めません(不倫の子?----失礼)。
(即ち#1の仕事をしません)

不運にも僕は例のxNode.add(cNode);を実行する前に別なところでcNodeに対して
cNode.setParent(node2);をやってしまいました。
(情報報告の欠如に心苦しい)

これでxNode.add(cNode)を実行して、insertの中で
node2.remove(cNode)の実行が失敗してしまいました。
node2が自分をとうちゃんと呼んでいるcNodeという子がどっかで生まれたのは
知る由もなっかたのですから。


======================
親子関係はあくまで双方的であると思えば、setParentというメソッドの存在は
不思議に感じます。

最後ですが
改めて御礼を申し上げます。

また宜しくお願い致します



[ メッセージ編集済み 編集者: isseki 編集日時 2003-05-11 14:46 ]
1

スキルアップ/キャリアアップ(JOB@IT)