JTree, TreeModel, etc
-
Hallo,
Ich kaempfe seit einigen Tagen mit dem JTree, dem TreeModel, etc und habe schon erfolglos in einigen Foren gepostet.Ziel:
Ich will bei einigen Blaettern die Moeglichkeit bieten, den Inhalt per JComboBox auswaehlen zu koennen. Bei anderen Blaettern sollte man den Inhalt editieren koennen, bei den uebrigen Knoten/Blaettern sollte sich nichts aendern. Dazu habe ich das folgende Beispiel geschrieben.Probleme:
- beim Blatt das sich unter "box" befindet, wird zwar die Box erzeugt, aber der ausgewaehlte Wert wird nicht uebernommen.- beim Blatt das sich unter "text" befindet, bekomme ich eine Exception statt einem Eingabeprompt.
- bei allen anderen Knoten, die nicht editierbar sein sollen, bekomme ich generell eine Exception.
Kann mir jemand an Hand des Beispiels helfen?
package treeDemo01; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Collection; import java.util.EventObject; import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.WindowConstants; import javax.swing.event.CellEditorListener; import javax.swing.event.ChangeEvent; import javax.swing.event.TreeModelListener; import javax.swing.tree.TreeCellEditor; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; import treeDemo01.TestTreeModel.Node; /** * The Frame. * * @author user */ public class TreeTest extends javax.swing.JFrame { private JScrollPane sp; private JTree tree; public static void main(String[] args) { TreeTest inst = new TreeTest(); inst.setVisible(true); } public TreeTest() { super(); initGUI(); } private void initGUI() { setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); sp = new JScrollPane(); tree = new JTree(new TestTreeModel()); tree.setEditable(true); tree.setCellEditor(new TestCellEditor()); sp.setViewportView(tree); getContentPane().add(sp); pack(); setSize(400, 300); } } /** * The TreeModel. * * @author user */ class TestTreeModel implements TreeModel{ private Node root = new Node(){ @Override public String toString() { return getContent(); } }; /* * methods */ public Object getRoot() { return root; } public Object getChild(Object parent, int index) { return ((Node) parent).getChildNodeAt(index); } public int getChildCount(Object parent) { return ((Node) parent).getChildCount(); } public boolean isLeaf(Object node) { return ((Node) node).isLeaf(); } public int getIndexOfChild(Object parent, Object child) { return ((Node) parent).getChildIndexOf(((Node) child).getContent()); } /* * default methods unimplemented!? */ public void valueForPathChanged(TreePath path, Object newValue) { // TODO Auto-generated method stub } public void addTreeModelListener(TreeModelListener l) { // TODO Auto-generated method stub } public void removeTreeModelListener(TreeModelListener l) { // TODO Auto-generated method stub } /** * The node type. * * @author user */ class Node{ protected String content; private Node[] children; private Node parent; private Entry entry; private int level; /** * ctor for root node */ public Node(){ init( "rootnode", null, 0); } public Node(String someText, Node parentNode){ init(someText, parentNode, parentNode.getLevel() + 1); } public Node(Entry someEntry, Node parentNode){ entry = someEntry; init(someEntry.getElementAt(someEntry.getSelectedElementIndex()) , parentNode, parentNode.getLevel() + 1); } /* * methods */ private void init(String text, Node parentNode, int thisLevel){ setLevel(thisLevel); setContent(text); setParent(parentNode); } public Node getChildNodeAt(int index) { generateChildNodes(); return children[index]; } public int getChildIndexOf(String szChildContent) { for(int cnt = 0; cnt < children.length; ++cnt){ if(children[cnt].getContent().equals(szChildContent)) return cnt; } return -1; } public String getContent() { return content; } public boolean isLeaf() { return (getLevel() == 2); } public int getChildCount(){ if(children == null){ generateChildNodes(); } return children.length; } /** * Contains the structure of the tree. */ private void generateChildNodes(){ if(children == null){ if(level == 0){ children = new Node[2]; children[0] = new Node("box", this); children[1] = new Node("text", this); } if(level == 1){ children = new Node[1]; if(this.getContent().equals("box")){ children[0] = new Node(new Entry(0, "tripple click me", "click", "last"), this); }else if(this.getContent().equals("text")){ children[0] = new Node("This text should be editable!", this); } } } } public String toString(){ return getContent(); } public Entry getEntry() { return entry; } public void setEntry(Entry entry) { this.entry = entry; } public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } public Node getParent() { return parent; } public void setParent(Node parent) { this.parent = parent; } public void setContent(String content) { this.content = content; } } } /** * The entry type used for the JComboBox later on. * * @author user */ class Entry{ private String[] elements; private int iSelected = 0; /* * Constructor. */ public Entry(int selectedIndex, String...items ){ setSelectedIndex(selectedIndex); elements = items; } /* * methods */ public int getElementsCount(){ return elements.length; } public String getElementAt(int index){ return elements[index]; } public int getSelectedElementIndex(){ return iSelected; } public void setSelectedIndex(int idx){ iSelected = idx; } @Override public String toString() { return getElementAt(getSelectedElementIndex() ); } } /** * The TreeCellEditor class. * * @author user */ class TestCellEditor implements TreeCellEditor { private Collection<CellEditorListener> listeners = new ArrayList<CellEditorListener>(); private DefaultComboBoxModel model; private JComboBox box; public TestCellEditor(){ model = new DefaultComboBoxModel(); box = new JComboBox(model); box.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ stopCellEditing(); } }); } /* * methods */ public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) { cancelCellEditing(); Node node = (Node) value; if(leaf && (node.getEntry() != null)){ Entry entry = node.getEntry(); model.removeAllElements(); for(int cnt = 0; cnt < entry.getElementsCount(); ++cnt){ model.addElement(entry.getElementAt(cnt)); } model.setSelectedItem(model.getElementAt(entry.getSelectedElementIndex())); return box; } return null; } public Object getCellEditorValue() { String[] elements = new String[model.getSize()]; for(int cnt = 0; cnt < elements.length; ++cnt){ elements[cnt] = (String) model.getElementAt(cnt); } int iSelected = model.getIndexOf( model.getSelectedItem()); return new Entry(iSelected, elements); } public boolean isCellEditable(EventObject anEvent) { if(anEvent instanceof MouseEvent){ return (((MouseEvent)anEvent).getClickCount() > 2); }else{ return true; } } public boolean shouldSelectCell(EventObject anEvent) { return true; } public boolean stopCellEditing() { ChangeEvent event = new ChangeEvent(this); for(CellEditorListener listener : listeners){ listener.editingStopped(event); } return true; } public void cancelCellEditing() { ChangeEvent event = new ChangeEvent(this); for(CellEditorListener listener:listeners){ listener.editingCanceled(event); } } public void addCellEditorListener(CellEditorListener l) { listeners.add(l); } public void removeCellEditorListener(CellEditorListener l) { listeners.remove(l); } }
-
http://www.phptr.com/articles/printerfriendly.asp?p=26327&rl=1
und
package treeDemo02; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Collection; import java.util.EventObject; import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.WindowConstants; import javax.swing.event.CellEditorListener; import javax.swing.event.ChangeEvent; import javax.swing.event.TreeModelListener; import javax.swing.tree.DefaultTreeCellEditor; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; /** * The Frame. * * @author user */ public class TreeTest extends javax.swing.JFrame { private JScrollPane sp; private CustomTree tree; public static void main(String[] args) { TreeTest inst = new TreeTest(); inst.setVisible(true); } public TreeTest() { super(); initGUI(); } private void initGUI() { setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); sp = new JScrollPane(); tree = new CustomTree(new TestTreeModel()); tree.setEditable(true); tree.setCellEditor(new TestCellEditor(tree)); sp.setViewportView(tree); getContentPane().add(sp); pack(); setSize(400, 300); } } /** * The TreeModel. * * @author user */ class TestTreeModel implements TreeModel{ private Node root = new Node(){ @Override public String toString() { return getContent(); } }; /* * methods */ public Object getRoot() { return root; } public Object getChild(Object parent, int index) { return ((Node) parent).getChildAt(index); } public int getChildCount(Object parent) { return ((Node) parent).getChildCount(); } public boolean isLeaf(Object node) { return ((Node) node).isLeaf(); } public int getIndexOfChild(Object parent, Object child) { return ((Node) parent).getChildIndexOf(((Node) child).getContent()); } /* * default methods unimplemented!? */ public void valueForPathChanged(TreePath path, Object newValue) { Node node = (Node) path.getLastPathComponent(); String sz = newValue.toString(); node.setContent(sz); } public void addTreeModelListener(TreeModelListener l) { // no adding } public void removeTreeModelListener(TreeModelListener l) { // no removing } } /** * The node type. * * @author user */ class Node{ protected String content; private Node[] children; private Node parent; private Entry entry = null; private int level; /** * ctor for root node */ public Node(){ init( "rootnode", null, 0); } public Node(String someText, Node parentNode){ init(someText, parentNode, parentNode.getLevel() + 1); } public Node(Entry someEntry, Node parentNode){ entry = someEntry; init(someEntry.getElementAt(someEntry.getSelectedElementIndex()) , parentNode, parentNode.getLevel() + 1); } /* * methods */ private void init(String text, Node parentNode, int thisLevel){ setLevel(thisLevel); setContent(text); setParent(parentNode); } public Node getChildAt(int index) { generateChildNodes(); return children[index]; } public int getChildIndexOf(String szChildContent) { for(int cnt = 0; cnt < children.length; ++cnt){ if(children[cnt].getContent().equals(szChildContent)) return cnt; } return -1; } public String getContent() { return content; } public boolean isLeaf() { return (getLevel() == 2); } public int getChildCount(){ if(children == null){ generateChildNodes(); } return children.length; } /** * Contains the structure of the tree. */ private void generateChildNodes(){ if(children == null){ if(level == 0){ children = new Node[2]; children[0] = new Node("box", this); children[1] = new Node("text", this); } if(level == 1){ children = new Node[1]; if(this.getContent().equals("box")){ children[0] = new Node(new Entry(0, "tripple click me", "click", "last"), this); }else if(this.getContent().equals("text")){ children[0] = new Node("This text should be editable!", this); } } } } public String toString(){ return getContent(); } public Entry getEntry() { return entry; } public void setEntry(Entry newEntry) { this.entry = newEntry; setContent(entry.getElementAt(entry.getSelectedElementIndex())); } public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } public Node getParent() { return parent; } public void setParent(Node parent) { this.parent = parent; } public void setContent(String content) { this.content = content; } public boolean hasEntryBox(){ if(!this.isLeaf()) return false; return this.entry != null; } public boolean hasTextField(){ if(!this.isLeaf()) return false; return this.entry == null; } } /** * The entry type used for the JComboBox later on. * * @author user */ class Entry{ private String[] elements; private int iSelected = 0; /* * Constructor. */ public Entry(int selectedIndex, String...items ){ elements = items; setSelectedIndex(selectedIndex); } /* * methods */ public int getElementsCount(){ return elements.length; } public String getElementAt(int index){ return elements[index]; } public int getSelectedElementIndex(){ return iSelected; } public void setSelectedIndex(int idx){ iSelected = idx; } @Override public String toString() { return getElementAt(getSelectedElementIndex() ); } } /** * The TreeCellEditor class. * * @author user */ class TestCellEditor extends DefaultTreeCellEditor{ private Collection<CellEditorListener> listeners = new ArrayList<CellEditorListener>(); private DefaultComboBoxModel model; private JComboBox box; private JTextField tf; private Component selected; public TestCellEditor(JTree tree) { super(tree, null); } /* * methods */ public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) { cancelCellEditing(); Node node = (Node) value; if(node.hasEntryBox()){ model = new DefaultComboBoxModel(); box = new JComboBox(model); box.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ stopCellEditing(); } }); Entry entry = node.getEntry(); model.removeAllElements(); for(int cnt = 0; cnt < entry.getElementsCount(); ++cnt){ model.addElement(entry.getElementAt(cnt)); } model.setSelectedItem(model.getElementAt(entry.getSelectedElementIndex())); this.selected = this.box; return box; }else if(node.hasTextField()){ tf = new JTextField(node.getContent()); tf.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ stopCellEditing(); } }); this.selected = this.tf; return tf; } return null; } public Object getCellEditorValue() { if(selected.equals(this.box)){ String[] elements = new String[model.getSize()]; for(int cnt = 0; cnt < elements.length; ++cnt){ elements[cnt] = (String) model.getElementAt(cnt); } int iSelected = model.getIndexOf( model.getSelectedItem()); return new Entry(iSelected, elements); }else if(selected.equals(this.tf)){ return tf.getText(); } return null; } public boolean isCellEditable(EventObject anEvent) { if(anEvent instanceof MouseEvent){ return (((MouseEvent)anEvent).getClickCount() > 2); }else{ return true; } } public boolean shouldSelectCell(EventObject anEvent) { return true; } public boolean stopCellEditing() { ChangeEvent event = new ChangeEvent(this); for(CellEditorListener listener : listeners){ listener.editingStopped(event); } return true; } public void cancelCellEditing() { ChangeEvent event = new ChangeEvent(this); for(CellEditorListener listener:listeners){ listener.editingCanceled(event); } } public void addCellEditorListener(CellEditorListener l) { listeners.add(l); } public void removeCellEditorListener(CellEditorListener l) { listeners.remove(l); } } /** * * @author user */ class CustomTree extends JTree{ public CustomTree(TestTreeModel model){ super(model); } public boolean isPathEditable(TreePath path){ if (isEditable()){ return getModel().isLeaf( path.getLastPathComponent()); } return false; } }