을 편집 한 후 JTree에있는 노드를 축소하지 방법 :노드가 I이 기능을 구현하는 방법을 알고 싶어
내가 노드의 이름을 편집 할 수있는 편집 가능한 JTree가 있습니다. 편집 할 때 분기 노드 (일부 리프 노드가 있음)가 있고이 분기 노드가 편집 중에 확장되면이 노드가 축소됩니다.
열려있는 경우 해당 분기 노드를 열어두고 편집이 완료되면 접힌 경우 축소됩니다.
방법이 트릭을 할 ...
나는 TreeWillExpandListener보고 시도했지만 내가이 메소드를 호출하기 전에 실제 노드 편집 모드에있는 경우 인식 할 필요가 있기 때문에 내 문제가 해결되지 않는 것 같다? 그것은 너무 분명한 일이지만 필요한 모든 답변을 찾을 수 없습니다 :/
좋아,이 코드는, 내가 그것을 설명하려고합니다. 우선, TreeModel을 구현하는 ContactTreeModel 클래스가 있습니다. 생성자는 주 앱 프레임에서 주소록과 그룹 관리자를로드하기 만하면 새 루트를 만들고 두 번째 방법에서는 데이터베이스에서 데이터를로드합니다.
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