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

Anmelden zum Antworten