JTree dentro de uma JTable

3 respostas
B

Galera,

Alguém já implementou uma jtree dinâmica dentro de uma jtable? Preciso fazer essa implementação, mas pelos exemplos que vi não consegui. Será que alguém poderia me dar uma força?

Grato.

3 Respostas

BiraBoy

Aproveitando este tópico.

Eu tenho um determinado objeto com uma coleção associada e quero renderizá-lo numa linha de um JTable. Numa das colunas, dentro da célula, terei um JTree com a coleção de objetos associados. Isso a cada linha.

Essa parte eu consegui. Outra coisa que quero é poder selecionar a linha para assim selecionar o objeto que é representado na linha. Consegui fazer isso também.

O problema é que quero selecionar um nó de um JTree dentro de uma célula no JTable(e acessar o objeto selecionado). Tenho pesquisado, mas não entendido nem conseguido resolver. Eis o que fiz e deu certo:

JTable treeTable = new JTable(presentationModel.getTableModel());
//Aqui uso JGoodies
treeTable.setSelectionModel(new SingleListSelectionAdapter(presentationModel.getOcupacaoSelectionInList().getSelectionIndexHolder()));
//Coluna da coleção de objetos
TableColumnModel tcm = treeTable.getColumnModel();
tcm.getColumn(3).setCellRenderer(new JTreeCellSinonimoRenderer());

Aqui segue o Renderer que usei:

public class JTreeCellSinonimoRenderer extends JTree implements TableCellRenderer {

	public Component getTableCellRendererComponent(JTable table,
			Object value, boolean isSelected, boolean hasFocus,
			int row, int column) {
		List<MeuObjeto> colecao = (List<MeuObjeto>) value;
		
		//A linha terá a altura equivalente a sua altura padrão(que é em pixels) multiplicada pelo número de meusObjetos(nós da árvore)
		//Se não houver meusObjetos, terá o tamanho padrão
		if(colecao.size()>0){
			table.setRowHeight(row, table.getRowHeight()*colecao.size());
		}
		
		//arvore de sinonimos
		DefaultMutableTreeNode root = new DefaultMutableTreeNode();
		for (MeuObjeto meuObjeto: colecao) {
			DefaultMutableTreeNode node = new DefaultMutableTreeNode(meuObjeto.getTitulo());
			root.add(node);
		}
		//JTree jTree = new JTree(root);
		DefaultTreeModel model = new DefaultTreeModel(root);
		this.setModel(model);
		
	    //retirando icones da arvore
	    DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
	    renderer.setOpenIcon(null);
	    renderer.setClosedIcon(null);
	    renderer.setLeafIcon(null);	    
	    
	    this.setCellRenderer(renderer);
	    this.setRootVisible(false);
	
	    return this;
	}

Para conseguir selecionar, tentei fazer, tomando por base o artigo deste site aqui, o seguinte CellEditor(que não deu certo):

public class MeuObjetoCellEditor extends JTree implements TableCellEditor {

	protected EventListenerList listenerList = new EventListenerList();
    protected ChangeEvent changeEvent = new ChangeEvent(this);
	
	public MeuObjetoCellEditor() {
		super();
		this.addTreeSelectionListener(new TreeSelectionListener(){
			public void valueChanged(TreeSelectionEvent event){
				fireEditingStopped();
			}
		});
	}

	public Component getTableCellEditorComponent(JTable table, Object
			value, boolean isSelected, int row, int column) {
		List<MeuObjeto> colecao = (List<MeuObjeto>) value;
		
		//A linha terá a altura equivalente a sua altura padrão(que é em pixels) multiplicada pelo número de meusObjetos(nós da árvore)
		//Se não houver meusObjetos, terá o tamanho padrão
		if(colecao.size()>0){
			table.setRowHeight(row, table.getRowHeight()*colecao.size());
		}
		
		//arvore de sinonimos
		DefaultMutableTreeNode root = new DefaultMutableTreeNode();
		for (MeuObjeto meuObjeto: colecao) {
			DefaultMutableTreeNode node = new DefaultMutableTreeNode(meuObjeto.getTitulo());
			root.add(node);
		}
		//JTree jTree = new JTree(root);
		DefaultTreeModel model = new DefaultTreeModel(root);
		this.setModel(model);
		
		//retirando icones da arvore
	    DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
	    renderer.setOpenIcon(null);
	    renderer.setClosedIcon(null);
	    renderer.setLeafIcon(null);	    
	    
	    this.setCellRenderer(renderer);
	    this.setRootVisible(false);

	    this.addMouseListener(new MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                System.out.println("Teste");
            }
        });

		
		return this;
    }

	protected void fireEditingStopped() {
		CellEditorListener listener;
		Object[] listeners = listenerList.getListenerList();
		for (int i = 0; i < listeners.length; i++) {
			if (listeners[i] == CellEditorListener.class) {
				listener = (CellEditorListener) listeners[i + 1];
				listener.editingStopped(changeEvent);
			} 
		} 
    } 

    protected void fireEditingCanceled() {
    	CellEditorListener listener;
    	Object[] listeners = listenerList.getListenerList();
    	for (int i = 0; i < listeners.length; i++) {
    		if (listeners[i] == CellEditorListener.class) {
    			listener = (CellEditorListener) listeners[i + 1];
    			listener.editingCanceled(changeEvent);
    		} 
    	} 
    } 
	
	public void addCellEditorListener(CellEditorListener listener) {
		listenerList.add(CellEditorListener.class, listener);
	}

	public void removeCellEditorListener(CellEditorListener listener) {
    	listenerList.remove(CellEditorListener.class, listener);
    }
	
	public void cancelCellEditing() {
		fireEditingCanceled();
	} 

    public boolean stopCellEditing() {
    	fireEditingStopped();
    	return true;
    } 

    public boolean isCellEditable(EventObject event) {
    	return true;
    } 
    
    public boolean shouldSelectCell(EventObject event) {
    	return true;
    } 

    public Object getCellEditorValue() {
    	DefaultMutableTreeNode node = (DefaultMutableTreeNode)this.getLastSelectedPathComponent();
		return node.getUserObject();
    } 
}
BiraBoy

Resolvi. Primeiro no TableModel eu adicionei:

public boolean isCellEditable(int row, int col) {
            //Com este algorítmo, estou dizendo que apenas a quarta coluna é editável
        	if (col != 3) {
                return false;
            } else {
                return true;
            }
        }

Na classe CellEditor eu adicionei o seguinte atributo para que receba a coleção de Objetos que representa o JTree da célula selecionada:

protected List<MeuObjeto> meuObjetos = new ArrayList<MeuObjeto>();

No getTableCellEditorComponent eu preencho esse atributo atribuindo o value da assinatura do método a essa propriedade:

E no getCellEditorValue eu fiz o seguinte:

public Object getCellEditorValue() {
    	DefaultMutableTreeNode node = (DefaultMutableTreeNode)this.getLastSelectedPathComponent();
    	int posicaoDesteNo = node.getParent().getIndex(node);
    	//recupera o objeto que está de acordo com o índice equivalente na hierarquia de Nós
    	return meusObjetos.get(posicaoDesteNo);
    }

Daí é soh dar um getColumnModel().getColumn(idColuna).getCellEditor().getCellEditorValue() que eu recupero este objeto

L

Olá galera… estou revivendo o tópico…
Sobre este componente implementado e demonstrado acima, tem como adicionar linhas na tabela dinamicamente, ou seja, ter um botão que adiciona uma linha na tabela,e por conseguência um nodo a mais na tree?

Criado 11 de julho de 2007
Ultima resposta 13 de nov. de 2008
Respostas 3
Participantes 3