を編集された後JTreeの中でノードを折りたたむない方法:ノードが、私はこの機能を実装する方法を知りたい
私は、ノードの名前を編集することができ、編集可能なJTreeのを持っています。私はいくつかの枝ノード(それにいくつかの葉ノードを持っています)を持っていて、編集中にこの枝ノードが展開されていると、編集後、このノードは崩壊します。
開いている場合はブランチノードを開いたままにしておき、折りたたまれている場合は編集後に折りたたんでいます。
どのようにこのトリックを行うために...
私はTreeWillExpandListenerを見てみましたが、私が、私はこれらのメソッドを呼び出す前に、実際のノードが編集モードであるかどうかを認識する必要があるので、それは私の問題を解決しないと思われますか?あまりにも明白ですが、私は答えを見つけることができません:/
これはコードなので、私はそれを説明しようとします。まず第一に、TreeModelを実装するContactTreeModelクラスがあります。コンストラクタはメインのアプリケーションフレームからアドレス帳とグループマネージャをロードするだけで、新しいルートを作成し、2番目の方法でデータベースからデータをロードします。
public ContactTreeModel() {
addressBookManager = ContactManagerFrame.getAddressBookManager();
groupManager = ContactManagerFrame.getGroupManager();
root = new DefaultMutableTreeNode();
processTreeHierarchy();
}
private void processTreeHierarchy() {
DefaultMutableTreeNode group, contact;
for (Group g : addressBookManager.getGroups()) {
group = new DefaultMutableTreeNode(g);
root.add(group);
for (Contact c : addressBookManager.getContactsFromGroup(g)) {
contact = new DefaultMutableTreeNode(c);
group.add(contact);
}
}
}
Iは、ユーザがnewValueにパスによって識別される項目の値を変更したときにメッセージとして送ら
場合TreeModelのメソッドvalueForPathChangedが解雇されていること。読み取りますnewValueが本当に新しい値を示す場合、モデルはtreeNodesChangedイベントをポストする必要があります。
だから私はこのような方法と書きました:
@Override
public void valueForPathChanged(TreePath path, Object newValue) {
// backup of the original group
Group oldGroup = (Group) path.getLastPathComponent();
try {
Group testGroup = (Group) path.getLastPathComponent();
testGroup.setName((String) newValue);
// validation of the group to be updated
groupManager.validateGroup(testGroup, true);
oldGroup.setName((String) newValue);
// updating of the group in db
groupManager.updateGroup(oldGroup);
} catch (ServiceFailureException | ValidationException ex) {
// if database error occured or validation exception is raised,
// update label in gui
ContactManagerFrame.getStatusPanelLabel().setText(ex.getMessage());
} finally {
fireTreeStructureChanged();
}
}
お知らせfinallyブロック内のメソッド、そのメソッドは、常に解雇されます。それはのように見える
protected void fireTreeStructureChanged() {
Object[] o = {root};
TreeModelEvent e = new TreeModelEvent(this, o);
for (TreeModelListener l : treeModelListeners) {
l.treeNodesChanged(e);
}
}
これは少しトリッキーで、なぜそれが動作しない(私は推測する)理由です。私はすべてのtreeModelListenerを繰り返し実行し、treeNodesChangedメソッドを起動します。
私もContactTreeModelおよび関連する方法でプライベート属性としてツリーモデルリスナーのために指定された配列している:最後のもの
private Vector<TreeModelListener> treeModelListeners = new Vector<>();
@Override
public void addTreeModelListener(TreeModelListener l) {
treeModelListeners.addElement(l);
}
@Override
public void removeTreeModelListener(TreeModelListener l) {
treeModelListeners.removeElement(l);
}
は、どのように私がモデルに追加モデルリスナーが見えますか?ここに来る:
public class ContactTreeModelListener implements TreeModelListener {
@Override
public void treeNodesChanged(TreeModelEvent e) {
System.out.println("nodes changed");
}
@Override
public void treeNodesInserted(TreeModelEvent e) {
System.out.println("nodes inserted");
}
@Override
public void treeNodesRemoved(TreeModelEvent e) {
System.out.println("nodes removed");
}
@Override
public void treeStructureChanged(TreeModelEvent e) {
System.out.println("structure changed");
}
}
これは基本的に何もしません。私は他の場所にリスナーを登録しましたが、今は関係ありません。
私はそれを実行すると、この状態では、ツリーは崩壊しておらず、その振る舞いは望まれます。しかし、元の文字列が約5文字で、それを4文字に変更した場合、ラベルには4文字だけでなく、5行目の空白も表示されますが、実際にはそのノード(ラベル)の名前が書き換えられます。そのラベルの編集が終わったら、元のラベルのサイズは変わりません。同様に、グループの名前を拡張すると、 というように4から5文字に名前を変更します。そのノードのラベルには、テキスト全体が表示するには大きすぎる を示すドットが含まれます。それは変です...どのように私はそのラベルのudpdate を作るのですか?
最後のこと...私はJTree +でカスタムアイコンを持っているので空のグループと非空のグループの間で認識を行います。ツリー内で何らかのアクションを実行するたびにdbの実際のアイコンをチェックする必要があります(私はノードを開いて閉じていても実行されていることを確認しました)。私は実際にキャッシングを行うDefaultTreeCellRendererを延長してこれは非常に非効率的である:
@Override
public Component getTreeCellRendererComponent(
JTree tree,
Object value,
boolean sel,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus) {
if (iconCache == null) {
throw new NullPointerException("iconCache in "
+ this.getClass().getName() + " is null");
}
super.getTreeCellRendererComponent(
tree, value, sel,
expanded, leaf, row,
hasFocus);
if (value instanceof Group) {
Group g = (Group) value;
Icon groupIcon = iconCache.get(g);
if (groupIcon == null) {
if (groupHasContacts(g)) {
groupIcon = groupNonEmpty;
} else {
groupIcon = groupEmptyIcon;
}
iconCache.put(g, groupIcon);
}
JLabel result = (JLabel) super.getTreeCellRendererComponent(tree,
g.getName(), sel, expanded, leaf, row, hasFocus);
result.setIcon(groupIcon);
return result;
}
else if (value instanceof Contact) {
Contact c = (Contact) value;
Icon icon = iconCache.get(c);
if (icon == null) {
icon = this.contactIcon;
iconCache.put(c, icon);
}
JLabel result = (JLabel) super.getTreeCellRendererComponent(
tree, c.getName() + c.getSurname(),
sel, expanded, leaf, row, hasFocus);
result.setIcon(icon);
return result;
}
JLabel defaultNode = (JLabel) super.getTreeCellRendererComponent(
tree, "?", sel, expanded, leaf, row, hasFocus);
defaultNode.setIcon(unknownNode);
return defaultNode;
}
なぜ最初から崩壊していますか?問題を説明する[SSCCE](http://sscce.org/)を共有してください。 – tenorsax
@Max説明のためにいくつかのコードを追加しました。役立つことを願っています... – stewenson