jTree Dinâmica

21 respostas
W

Olá Pessoal!!!

Mais uma vez recorrendo a vcs, tenho uma duvida referente a como montar uma Jtree dinamica, não sei mesmo por onde começar, a Jtree sera montada atraves de uma consulta do banco de dados, pois deste modo criarei perfis de usuario no banco de dados para restringir algums acessos ao qual o usuario não tem necessidade de ter no sistema ao qual eu estou fzd, a Jtree esta pronta porem esta com os nós fixos, se alguem tiver outras ideias de como criar regras de acesso posta ai, quem sabe a ideia é melhor e mais viavel que a minha, quem poder me ajudar fico extremamente agradecido, valeu passoal.

21 Respostas

V

cada nó da tree pode armazenar uma referência para um objeto,

é só você criar a tree e iterar sua coleção de usuários e adicionando os objetos pesquisado na tree.

É isso que você quer fazer??

vlw

W

vinidouradoh:
cada nó da tree pode armazenar uma referência para um objeto,

é só você criar a tree e iterar sua coleção de usuários e adicionando os objetos pesquisado na tree.

É isso que você quer fazer??

vlw

Cara obrigado pela resposta mas naum consegui entender bem oq vc sugeriu, poderia ser um pouco mais claro pois ainda não tenho muito conhecimento em java entende?

V

Comece estudando o funcionamento do TreeModel. Saiba como o model se comunica com a Tree, e que eventos devem ser disparados quando a JTree muda.
http://www.guj.com.br/posts/list/37821.java#501820

Você até pode tentar fazer com o DefaultMutableTreeNode. Mas esse geralmente é o jeito menos prático e mais difícil. Via de regra, fuja dos “Default” do Swing.

Só um detalhe. O JTree é um dos componentes mais complexos do Swing.

W

ViniGodoy:
Comece estudando o funcionamento do TreeModel. Saiba como o model se comunica com a Tree, e que eventos devem ser disparados quando a JTree muda.
http://www.guj.com.br/posts/list/37821.java#501820

Você até pode tentar fazer com o DefaultMutableTreeNode. Mas esse geralmente é o jeito menos prático e mais difícil. Via de regra, fuja dos “Default” do Swing.

Só um detalhe. O JTree é um dos componentes mais complexos do Swing.

Valeu ViniGodoy, ja deu uma clareada, vc sabe algum livro que tenha uma abordagem legal sobre jTree, jTable…Muito obrigada pela força. Abraço!!!

V

O livro do Swing da O’Reilly tem.

A

Olá, sou novo aqui no grupo, e novo no java tbm, estou aprendendo por conta para dar conta da uma iniciação cientifica na minha facul…

Bem, quanto as jtree, estou estudando sobre elas tbm, e estou utilizando o material do site da sun… do seu “super tutorial java”, segue o link relativo a jtrees

http://java.sun.com/docs/books/tutorial/uiswing/components/tree.html

espero ter ajudado,

André.

B

ViniGodoy:
Comece estudando o funcionamento do TreeModel. Saiba como o model se comunica com a Tree, e que eventos devem ser disparados quando a JTree muda.
http://www.guj.com.br/posts/list/37821.java#501820

Você até pode tentar fazer com o DefaultMutableTreeNode. Mas esse geralmente é o jeito menos prático e mais difícil. Via de regra, fuja dos “Default” do Swing.

Só um detalhe. O JTree é um dos componentes mais complexos do Swing.

ViniGodoy,

Irmão boa tarde, gostaria de lhe pedir uma ajuda, poderia me mostrar um exemplo com subcategorias? Seu exemplo eu entendi legal, mas não to conseguindo entender como colocar um nó dentro de outro. Se puder me dar uma força agradeço.

V

O exemplo tem subcategorias.

B

O exemplo tem subcategorias.

Irmão,

Acho que não expliquei direito o que eu quis dizer, na real preciso com 3 níveis ou mais tipo assim:

Raiz
—Categoria1
------SubCategoria1.1
---------Item xyz
---------item joj
---------item hnihi
------SubCategoria1.2
------Item ihihji
------Item jnknk
------SubCategoria1.3
---------Item hhhhh
---------Item kkkkk

----Categoria2
------SubCategoria2.1
---------Item xyz
---------item joj
---------item hnihi
----SubCategoria2.2
---------Item ihihji
---------Item jnknk
----SubCategoria2.3
---------Item hhhhh
---------Item kkkkk

Seguindo seu exemplo, seria mais ou menos como colocar um livro “dentro” de outro… to quebrando a cabeça e não sei por onde começar…

V

E como são as classes que representam essa informação?

B
ViniGodoy:
E como são as classes que representam essa informação?

Então, antes de mais nada quero agradecer sua prontificação em ajudar-me.

As classes eu copiei das suas para compreender o funcionamento da coisa toda, aí fiz as alterações seguintes alterações:

A sua classe Livros alterei para Categorias:

public class Categorias {
	private String nome;
	private List<Categorias> subcategorias = new ArrayList<>();
                private List<Itens> itens = new ArrayList<>();
        

	public Categorias(String nome) {
		this.nome = nome;
	}

	public String getNome() {
		return nome;
	}

	@Override
	public String toString() {
		return getNome();
	}

	public void addItem(Itens item) {
		itens.add(item);
	}
        public void addSubCategoria(Categorias subCategorias){
            subcategorias.add(subCategorias);
        }
	public List<Categorias> getSubCategorias() {
		return Collections.unmodifiableList(subcategorias);
	}        
	public List<Itens> getItens() {
		return Collections.unmodifiableList(itens);
	}
        public int getNumSubCategorias(){
            return subcategorias.size();
        }
}

A Classe Autores Alterei para Itens:

public class Itens {
	private String nome;

	public Itens(String nome) {
		this.nome = nome;
	}

	public String getNome() {
		return nome;
	}

	@Override
	public String toString() {
		return getNome();
	}
}

A idéia é Adicionar uma Categoria, dentro desta categoria posso adicionar um item ou uma categoria e assim sucetivamente, não sei se minha lógica esta errada...

Fiz algumas alterações na sua Model para tentar monter isso mas não estou conseguindo ir pra frente..

A model modificada:

public class LivroTreeModel extends AbstractTreeModel {
	// Raiz da nossa árvore, vamos exibir uma lista de livros.
	private List<Categorias> livros;
        private String fakeRoot = "Livros";

	public LivroTreeModel(List<Categorias> livros) {
		this.livros = livros;
	}

	/**
	 * Com esse método, o Java quem é o objeto que está num determinado índice
	 * do pai. Cada nó de uma árvore pode ser encarado como uma lista. Sendo o
	 * pai a lista e o índice um dos filhos.
	 *
	 * @param parent
	 *            É o pai, que tem os filhos. No caso do Livro, o próprio livro.
	 * @param index
	 *            Índice do filho. No caso do livro, o índice corresponde aos
	 *            autores.
	 */
	public Object getChild(Object parent, int index) {
		if (parent == fakeRoot) // É o nó principal?
			return livros.get(index); // Pegamos da lista de livro

		if (parent instanceof Categorias) // O pai é uma categoria?
		{
                    if (((Categorias) parent).getNumSubCategorias() > 0) //O pai possui alguma subcategoria?
                    {
                        return ((Categorias) parent).getSubCategorias().get(index);
                    }else{
			// Devolvemos um Item
			return ((Categorias) parent).getItens().get(index); // Se não lista os itens(filhos)
                    }
		}

		// Se o pai não é nenhum desses. Melhor dar erro.
		throw new IllegalArgumentException("Invalid parent class"
				+ parent.getClass().getSimpleName());
	}

	/**
	 * Retornamos quantos filhos um pai tem. No caso de um livro, é a contagem
	 * de autores. No caso da lista de livros, é a quantidade de livros.
	 */
	public int getChildCount(Object parent) {
		// Mesma lógica.
		if (parent == fakeRoot)
			return livros.size();

		if (parent instanceof Categorias) // O pai é um livro?
			return ((Categorias) parent).getItens().size();

		// Se o pai não é nenhum desses. Melhor dar erro.
		throw new IllegalArgumentException("Invalid parent class"
				+ parent.getClass().getSimpleName());
	}

	/**
	 * Dado um pai, indicamos qual é o índice do filho correspondente.
	 */
	public int getIndexOfChild(Object parent, Object child) {
		if (parent == fakeRoot)
			return livros.indexOf(child);
		if (parent instanceof Categorias)
			return ((Categorias) parent).getItens().indexOf(child);

		return 0;
	}

	/**
	 * Devemos retornar quem é o nó raiz da árvore. Afinal, a árvore tem que
	 * começar em algum lugar.
	 */
	public Object getRoot() {
		return fakeRoot;
	}

	/**
	 * Indicamos se um nó é ou não uma folha. Isso é, se ele não tem filhos. No
	 * nosso caso, os autores são as folhas da árvore.
	 */
	public boolean isLeaf(Object node) {
		return node instanceof Itens;
	}

        public void adicionarLivro(Categorias livro)
        {
            livros.add(livro);
            fireLastPathComponentInserted(fakeRoot, livro);
        }

        public void adicionarSubLivro(Categorias livroPai, Categorias livro)
        {
            for (int i = 0; i < livros.size(); i++)
            {
                if (livros.get(i).getNome().equals(livroPai.getNome()))
                {
                    livros.get(i).addSubCategoria(livro);
                }
            }
            
            //livros.get(livroPai.get).addSubCategoria(livro);
            
            fireLastPathComponentInserted(fakeRoot, livroPai);
        }        
        
        public void adicionarAutor(Categorias livro, Itens autor)
        {
            livro.addItem(autor);
            fireLastPathComponentInserted(fakeRoot, livro, autor);
        }

        public void removerLivro(Categorias livro)
        {
            if (livros.remove(livro))
            {
                fireLastPathComponentRemoved(fakeRoot, livro);
            }
        }
}
V

Parece quase pronto. No entanto, quando você exibe os itens? Todas as categorias, não importando o nível, podem ter itens? Ou só as folhas?

B

O ideal seria ter folhas e itens

V

Então o getChildCount() da categoria deveria ser o size das subcategorias + o size da lista de itens.

O getChild da categoria deveria retornar:
a) Uma subcategoria, caso o index recebido no parâmetro seja < tamanho das subcategorias;
b) Um item, caso o índice seja > tamanho das subcategorias. Nesse caso, o índice será o index recebido no método - o tamanho da lista de subcategorias.

Como itens e categorias são coisas diferentes, o ideal seria especificar um renderer para o nó, para facilitar a distinção entre os dois. Quanto a isso, veja:
http://docs.oracle.com/javase/tutorial/uiswing/components/tree.html#display

B

ViniGodoy:
Então o getChildCount() da categoria deveria ser o size das subcategorias + o size da lista de itens.

O getChild da categoria deveria retornar:
a) Uma subcategoria, caso o index recebido no parâmetro seja < tamanho das subcategorias;
b) Um item, caso o índice seja > tamanho das subcategorias. Nesse caso, o índice será o index recebido no método - o tamanho da lista de subcategorias.

Como itens e categorias são coisas diferentes, o ideal seria especificar um renderer para o nó, para facilitar a distinção entre os dois. Quanto a isso, veja:
http://docs.oracle.com/javase/tutorial/uiswing/components/tree.html#display

Valeu irmão vou estudar essa parada, vou postando as dúvidas aqui… eta componente complicadinho de trabalhar ein…

V

Veja:

public class CategoriaTreeModel extends AbstractTreeModel {
	// Raiz da nossa árvore, vamos exibir uma lista de livros.
	private List&lt;Categorias&gt; categorias;
        private String fakeRoot = "Categorias";

	public LivroTreeModel(List&lt;Categorias&gt; categorias) {
		this.categorias = categorias;
	}

	/**
	 * Com esse método, o Java quem é o objeto que está num determinado índice
	 * do pai. Cada nó de uma árvore pode ser encarado como uma lista. Sendo o
	 * pai a lista e o índice um dos filhos.
	 *
	 * @param parent
	 *            É o pai, que tem os filhos. No caso do Livro, o próprio livro.
	 * @param index
	 *            Índice do filho. No caso do livro, o índice corresponde aos
	 *            autores.
	 */
	public Object getChild(Object parent, int index) {
		if (parent == fakeRoot) // É o nó principal?
			return categorias.get(index); // Pegamos da lista de livro

		if (parent instanceof Categorias) // O pai é uma categoria?
		{
			Categorias cat = (Categorias) categorias;
			if (index &lt; cat.getNumSubCategorias().size()) {
				return cat.getItens().get(index);
			}  
			return cat.getItens().get(index - cat.getNumSubCategorias().size()); 
		}
	}

	/**
	 * Retornamos quantos filhos um pai tem. No caso de um livro, é a contagem
	 * de autores. No caso da lista de livros, é a quantidade de livros.
	 */
	public int getChildCount(Object parent) {
		// Mesma lógica.
		if (parent == fakeRoot)
			return categorias.size();

		if (parent instanceof Categorias) {
			Categorias cat = (Categorias) parent;
			return cat.getSubcategorias.getSize() + cat.getItens().size();
		}
	}

	/**
	 * Dado um pai, indicamos qual é o índice do filho correspondente.
	 */
	public int getIndexOfChild(Object parent, Object child) {
		if (parent == fakeRoot)
			return livros.indexOf(child);
		if (parent instanceof Categorias) {
			if (child instanceof Categorias)
			     return ((Categorias) parent).getSubcategorias().indexOf(child);
			return ((Categorias) parent).getSubcategorias().size() + 
			     ((Categorias) parent).getItens().indexOf(child);
		}

		return 0;
	}

	/**
	 * Devemos retornar quem é o nó raiz da árvore. Afinal, a árvore tem que
	 * começar em algum lugar.
	 */
	public Object getRoot() {
		return fakeRoot;
	}

	/**
	 * Indicamos se um nó é ou não uma folha. Isso é, se ele não tem filhos. No
	 * nosso caso, os autores são as folhas da árvore.
	 */
	public boolean isLeaf(Object node) {
		return node instanceof Itens;
	}
}
V

Árvore é sempre o cão.

B
ViniGodoy:
bugalaws:
Valeu irmão vou estudar essa parada, vou postando as dúvidas aqui... eta componente complicadinho de trabalhar ein...

Árvore é sempre o cão.

Então irmão, com suas dicas e mais umas alterações(bem poucas..) consegui adicionar uma categoria dentro de outra, agora só falta eu descobrir como colocar uma folha nessa segunda categoria. Vou estudar melhor a parte do getChild acho que é alguma coisa por ali, pois está adicionando a folha(no meu caso um item) dentro do ArrayList da subcategoria, a parada está só na exibição da Folha dentro da árvore mesmo..

Minha classe CategoriasTreeModel está assim no momento:

package treeSample;

import java.util.ArrayList;
import java.util.List;
import javax.swing.tree.TreePath;

public class CategoriaTreeModel extends AbstractTreeModel {
	// Raiz da nossa árvore, vamos exibir uma lista de livros.
	private List&lt;Categorias&gt; categorias;
        private Categorias fakeRoot = new Categorias("Raiz Categorias");
        
        
	public CategoriaTreeModel(List&lt;Categorias&gt; categorias) {
	    this.categorias = categorias;
            
            //Se a categoria é vazia(adiciona a raiz nela)
            if (categorias.isEmpty())
            {
                categorias.add(fakeRoot);
            }
	}

	/**
	 * Com esse método, o Java quem é o objeto que está num determinado índice
	 * do pai. Cada nó de uma árvore pode ser encarado como uma lista. Sendo o
	 * pai a lista e o índice um dos filhos.
	 *
	 * @param parent
	 *            É o pai, que tem os filhos. No caso do Livro, o próprio livro.
	 * @param index
	 *            Índice do filho. No caso do livro, o índice corresponde aos
	 *            autores.
	 */
        @Override
	public Object getChild(Object parent, int index) {
                
//		if (parent == fakeRoot) // É o nó principal?
//			return categorias.get(index); // Pegamos da lista de livro

		if (parent instanceof Categorias) // O pai é uma categoria?
		{
			//List&lt;Categorias&gt; cat = categorias;
			if (index &lt; ((Categorias) parent).getSubCategorias().size()) {
				return ((Categorias) parent).getSubCategorias().get(index);
			}  
                        
                            return ((Categorias) parent).getItens().get(index - ((Categorias) parent).getSubCategorias().size()); // Se não lista os itens(filhos)
               }
            return null;
	}

	/**
	 * Retornamos quantos filhos um pai tem. No caso de um livro, é a contagem
	 * de autores. No caso da lista de livros, é a quantidade de livros.
	 */
        @Override
	public int getChildCount(Object parent) {
		// Mesma lógica.
//		if (parent == fakeRoot)
//			return categorias.size();

		if (parent instanceof Categorias) {
			Categorias cat = (Categorias) parent;
			return cat.getSubCategorias().size() + cat.getItens().size();
		}
            return 0;
	}

	/**
	 * Dado um pai, indicamos qual é o índice do filho correspondente.
	 */
        @Override
	public int getIndexOfChild(Object parent, Object child) {
		//if (parent == fakeRoot)
		//	return categorias.indexOf(child);
		if (parent instanceof Categorias) {
			if (child instanceof Categorias)
			     return ((Categorias) parent).getSubCategorias().indexOf(child);
                        
			return ((Categorias) parent).getSubCategorias().size() + ((Categorias) parent).getItens().indexOf(child);
		}

		return 0;
	}

	/**
	 * Devemos retornar quem é o nó raiz da árvore. Afinal, a árvore tem que
	 * começar em algum lugar.
	 */
        @Override
	public Object getRoot() {
		return fakeRoot;
	}

	/**
	 * Indicamos se um nó é ou não uma folha. Isso é, se ele não tem filhos. No
	 * nosso caso, os autores são as folhas da árvore.
	 */
        @Override
	public boolean isLeaf(Object node) {

                return node instanceof Itens;
	}
        
        //Medoto que chama as rotinas para adição de novas categorias/subcategorias
        public void adicionarCategoria(Categorias _categSelecionada, Categorias _categoria)
        {
            //Obtem a categoria &quot;pai&quot; no array de categorias para adição de nova categoria
            Categorias categAdd = percorreCategorias(categorias, _categSelecionada);
            
            //Adiciona a nova categoria
            categAdd.addSubCategoria(_categoria);
            
            //monta o caminho para exibição do treeview
            fireLastPathComponentInserted(montaPath(_categoria, null));
        }        
        
        //Percorre recursivamente o ArrayList Categorias
        //retornando a classe selecionada
        public Categorias percorreCategorias(List&lt;Categorias&gt; arrCategorias, Categorias categSelecionada)
        {
            Categorias retorno = null;
            //Percorre o arraylist para adicionar as novas categorias
            for (int i = 0; i &lt; arrCategorias.size(); i++)
            {
                if (arrCategorias.get(i) == categSelecionada)
                {
                        retorno = arrCategorias.get(i);
                        if(retorno != null)
                        {
                            return retorno;
                        }                        
                }else{

                    if(arrCategorias.get(i).getSubCategorias().size() &gt; 0)
                    {
                        retorno = percorreSubCategorias(arrCategorias.get(i), categSelecionada);
                        if(retorno != null)
                        {
                            return retorno;
                        }                        
                    }
                }
            } 
            return retorno;
        }
        
        //Metodo para percorrer recursivamente as subcategorias do ArrayList categorias 
        //para adicionar as novas categorias no Array
        public Categorias percorreSubCategorias(Categorias categI, Categorias categSelecionada)
        {
            Categorias retorno;
            for (int i = 0; i &lt; categI.getSubCategorias().size(); i++)
            {
                if (categI.getSubCategorias().get(i) == categSelecionada)
                {
                        retorno = categI.getSubCategorias().get(i);
                        if(retorno != null)
                        {
                            return retorno;
                        }
                }else{

                    if(categI.getSubCategorias().get(i).getSubCategorias().size() &gt; 0)
                    {
                        retorno = percorreSubCategorias(categI.getSubCategorias().get(i), categSelecionada);
                        if(retorno != null)
                        {
                            return retorno;
                        }                        
                    }
                }
            }
            return null;
        }
        
        public void adicionarItem(Categorias _categorias, Itens _item)
        {
            _categorias.addItem(_item);
            fireLastPathComponentInserted((Object[])montaPath(null, _item));
        }
        
        public void remover( Object itemSelecionado)
        {
            if(itemSelecionado instanceof Categorias)
            {
                //Monta o Path para notificar a exclusão do nó
                Object[] objPath = montaPath((Categorias)itemSelecionado, null);
                TreePath path =  new TreePath(objPath);
                
                //Obtem o parent na tree para pesquisar no array list a clase &quot;pai&quot;
                Object parent = path.getParentPath().getLastPathComponent();
                
                //Notifica a exclusão do nó
                fireLastPathComponentRemoved(objPath);
                
                //Retorna a classe do pai do objeto selecionado
                //para excluir o objeto selecionado
                Categorias teste = percorreCategorias(categorias, (Categorias)parent);
                //Remove da classe &quot;pai&quot; o &quot;filho&quot; selecionado
                teste.removeSubCategoria((Categorias)itemSelecionado);

            }
            
            if(itemSelecionado instanceof Itens)
            {
                //Monta o Path para notificar a exclusão do nó
                Object[] objPath = montaPath(null, (Itens)itemSelecionado);
                TreePath path =  new TreePath(objPath);
                //Obtem o parent na tree para pesquisar no array list a clase &quot;pai&quot;
                Object parent = path.getParentPath().getLastPathComponent();
                
                //Notifica a exclusão do item
                fireLastPathComponentRemoved(objPath);
                
                //Retorna a classe do pai do objeto selecionado
                //para excluir o objeto selecionado
                Categorias teste = percorreCategorias(categorias, (Categorias)parent);
                //Remove da classe &quot;pai&quot; o &quot;filho&quot; selecionado
                teste.removeItens((Itens)itemSelecionado);

            }            

        }

        
        //Método para percorrer o ArrayList categorias para montar o Path do menu selecionado
        //public Object[] montaPath(Object sel)
        public Object[] montaPath(Categorias _categoriaProcurada, Itens _item)
        {
            Object[] retorno = new Object[0];
            
            if(_categoriaProcurada != null) //Está procurando uma categoria?
            {
                for(Categorias categs : categorias) 
                {
                    //Percorre recursivamente o arraylist categorias e suas subcategorias
                    List&lt;Categorias&gt; arrVarreSub = (List&lt;Categorias&gt;) varreSub(categs, _categoriaProcurada, null);
                    if (arrVarreSub != null)
                    {
                        for(Categorias retVarre : arrVarreSub)
                        {
                            int ictrl = retorno.length;
                            retorno = (Object[]) resizeArray(retorno, retorno.length + 1);
                            retorno[ictrl] = retVarre;                               
                        }
                        return retorno;
                    }
                }
            }
            
            if(_item != null){ //Está procurando um Item ?
                
                for(Categorias categs : categorias)
                {
                    //Percorre os itens na raiz
                    for(Itens item : categs.getItens())
                    {
                        //Se o item for igual 
                        if(item == _item)
                        {
                            retorno = (Object[]) resizeArray(retorno, retorno.length + 1);
                            retorno[retorno.length - 1] = categs;       
                            
                            retorno = (Object[]) resizeArray(retorno, retorno.length + 1);
                            retorno[retorno.length -1] = item;
                            return retorno;
                        }
                        
                    }
                    if(categs.getSubCategorias().size() &gt; 0)
                    {
                        List&lt;Object&gt; arrVarreSub = (List&lt;Object&gt;) varreSub(categs, null, _item);
                        if (arrVarreSub != null)
                        {
                            for(Object obj : arrVarreSub)
                            {
                                retorno = (Object[]) resizeArray(retorno, retorno.length + 1);
                                retorno[retorno.length -1] = obj;                       
                            }
                            return retorno;
                        }
                    }
                }
                
            }
        return null;
        }
        
        //Rotina para montar o Path baseado na categoria ou item selecionado
        public Object varreSub(Categorias _categorias, Object _categSel, Itens _itemSel)
        {
            List&lt;Object&gt; retorno = new ArrayList();

                retorno.add(_categorias);


                for (Categorias categs : _categorias.getSubCategorias())
                {
                    retorno.add(categs);
                    
                    for(Itens _item : categs.getItens())
                    {
                        if(_item == _itemSel)
                        {
                            retorno.add(_item);
                            return retorno; 
                        }
                    }
                    retorno.remove(categs);
                    
                    if(categs == _categSel)
                    {
                        retorno.add(categs);
                        return retorno;
                    }

                    if(categs.getSubCategorias().size() &gt; 0)
                    {
                        for (Categorias _categs : categs.getSubCategorias())
                        {
                            retorno.add(categs);

                            for(Itens _item : _categs.getItens())
                            {
                                retorno.add(_categs);
                                if(_item == _itemSel)
                                {
                                    retorno.add(_item);
                                    return retorno; 
                                }
                                retorno.remove(_categs);
                            }                            

                            if(_categs == _categSel)
                            {
                                retorno.add(_categs);
                                return retorno;
                            }

                            if(_categs.getSubCategorias().size() &gt; 0)
                            {
                                List&lt;Object&gt; arrVarreSub = (List&lt;Object&gt;) varreSub(_categs, (Categorias) _categSel, _itemSel);
                                if (arrVarreSub != null)
                                {
                                    for(Object retVarre : arrVarreSub)
                                    {
                                       retorno.add(retVarre);
                                    }
                                    return retorno;
                                }
                            }

                            retorno.remove(categs);
                        }
                    }
                }
                return null;
            }

        //Rotina complementar da rotina varresub
        //Percorre as subcategorias da tree recursivamente
        public Object varreSubCateg(Categorias categ, Categorias categSel)
        {
            List&lt;Object&gt; retorno = new ArrayList();
            
            for(Categorias categs : categ.getSubCategorias())
            {
                if(categs == categSel)
                {
                    retorno.add(categ);
                    retorno.add(categs);
                    return retorno;
                }
                
                if(categs.getSubCategorias().size() &gt; 0)
                {
                    List&lt;Categorias&gt; arrVarreSub = (List&lt;Categorias&gt;) varreSubCateg(categs, (Categorias) categSel);
                    if (arrVarreSub != null)
                    {
                        retorno.add(categ);
                        for(Categorias retVarre : arrVarreSub)
                        {
                           retorno.add(retVarre);
                        }
                        return retorno;
                    }
                }
            }           
            return null;
        }
        
        //Rotina para redimensionar Arrays
        private static Object resizeArray (Object oldArray, int newSize) {
            int oldSize = java.lang.reflect.Array.getLength(oldArray);
            Class elementType = oldArray.getClass().getComponentType();
            Object newArray = java.lang.reflect.Array.newInstance(elementType, newSize);
            int preserveLength = Math.min(oldSize, newSize);
            if (preserveLength &gt; 0)
               System.arraycopy(oldArray, 0, newArray, 0, preserveLength);
            return newArray; 
        }
}
B

To tentando entender a parada de rederizar o nó separado da folha mas ta punk… rsss

B

Então irmão,

consegui acertar a parada aqui, porém o código ficou meio sujo, queria ver se consigo melhorar para deixar mais dinâmico, e com mais possibilidades de níveis, segue a Classe CategoriasTreeModel com as alterações feitas, porém está meio tosco o negócio, to tentando bolar um jeito de melhorar, se tiver alguma dica agradeço, eu criei um método getPai para quando um filho possuir um pai passar o path completo para o fireLastPathComponentInserted (vide método adicionarAutor), to pensando em adicionar um campo path na classe das categorias e na classe itens, dessa forma teria em cada classe qual o seu path completo podendo assim fazer os tratamentos necessários.

package treeSample;

import java.util.ArrayList;
import java.util.List;

public class CategoriaTreeModel extends AbstractTreeModel {
	// Raiz da nossa árvore, vamos exibir uma lista de livros.
	private List<Categorias> categorias;
        private String fakeRoot = "Categorias";

	public CategoriaTreeModel(List<Categorias> categorias) {
		this.categorias = categorias;
	}

	/**
	 * Com esse método, o Java quem é o objeto que está num determinado índice
	 * do pai. Cada nó de uma árvore pode ser encarado como uma lista. Sendo o
	 * pai a lista e o índice um dos filhos.
	 *
	 * @param parent
	 *            É o pai, que tem os filhos. No caso do Livro, o próprio livro.
	 * @param index
	 *            Índice do filho. No caso do livro, o índice corresponde aos
	 *            autores.
	 */
        @Override
	public Object getChild(Object parent, int index) {
                
		if (parent == fakeRoot) // É o nó principal?
			return categorias.get(index); // Pegamos da lista de livro

		if (parent instanceof Categorias) // O pai é uma categoria?
		{
			//List<Categorias> cat = categorias;
			if (index < ((Categorias) parent).getNumSubCategorias()) {
				return ((Categorias) parent).getSubCategorias().get(index);
			}  
                        
                            return ((Categorias) parent).getItens().get(index - ((Categorias) parent).getNumSubCategorias()); // Se não lista os itens(filhos)
               }
            return null;
	}

	/**
	 * Retornamos quantos filhos um pai tem. No caso de um livro, é a contagem
	 * de autores. No caso da lista de livros, é a quantidade de livros.
	 */
        @Override
	public int getChildCount(Object parent) {
		// Mesma lógica.
		if (parent == fakeRoot)
			return categorias.size();

		if (parent instanceof Categorias) {
			Categorias cat = (Categorias) parent;
			return cat.getSubCategorias().size() + cat.getItens().size();
		}
            return 0;
	}

	/**
	 * Dado um pai, indicamos qual é o índice do filho correspondente.
	 */
	public int getIndexOfChild(Object parent, Object child) {
		if (parent == fakeRoot)
			return categorias.indexOf(child);
		if (parent instanceof Categorias) {
			if (child instanceof Categorias)
			     return ((Categorias) parent).getSubCategorias().indexOf(child);
			return ((Categorias) parent).getSubCategorias().size() + 
			     ((Categorias) parent).getItens().indexOf(child);
		}

		return 0;
	}

	/**
	 * Devemos retornar quem é o nó raiz da árvore. Afinal, a árvore tem que
	 * começar em algum lugar.
	 */
	public Object getRoot() {
		return fakeRoot;
	}

	/**
	 * Indicamos se um nó é ou não uma folha. Isso é, se ele não tem filhos. No
	 * nosso caso, os autores são as folhas da árvore.
	 */
	public boolean isLeaf(Object node) {

                return node instanceof Itens;
	}
        
        public void adicionarLivro(Categorias livro)
        {
            categorias.add(livro);
            fireLastPathComponentInserted(fakeRoot, livro);
        }

        public void adicionarSubLivro(Categorias livroPai, Categorias livro)
        {
            for (int i = 0; i < categorias.size(); i++)
            {
                if (categorias.get(i).getNome().equals(livroPai.getNome()))
                {
                    livro.setPai(livroPai.getNome());
                    categorias.get(i).addSubCategoria(livro);
                }
            }
            
            //livros.get(livroPai.get).addSubCategoria(livro);
            
            fireLastPathComponentInserted(fakeRoot, livroPai, livro);
        }        
        
        public void adicionarAutor(Categorias livro, Itens autor)
        {
            livro.addItem(autor);
            if(livro.getPai() != null)
            {
                fireLastPathComponentInserted(fakeRoot,getPai(livro),livro, autor); 
            }else
            fireLastPathComponentInserted(fakeRoot,livro, autor);
        }
public Categorias getPai(Categorias filho){
    for (int i = 0; i < categorias.size(); i++)
    {
        if (categorias.get(i).getNome() == filho.getPai())
            return categorias.get(i);
    }
    
    return null;
}
        public void removerLivro(Categorias livro)
        {
            if (categorias.remove(livro))
            {
                fireLastPathComponentRemoved(fakeRoot, livro);
            }
        }
}
B

Árvore é sempre o cão.

Então irmão depois de umas noites sem dormir e uns dias a fio, consegui funcionar sem limite de níveis, afemaria… que trampo rsss pq que um abençoado não disponibiliza uma classe dessas para facilitar a vida… da uma olhada como ficou a minha CategoriaTreeModel :

package treeSample;

import java.util.ArrayList;
import java.util.List;
import javax.swing.tree.TreePath;

public class CategoriaTreeModel extends AbstractTreeModel {
	// Raiz da nossa árvore, vamos exibir uma lista de livros.
	private List&lt;Categorias&gt; categorias;
        private Categorias fakeRoot = new Categorias("Raiz Categorias");
        
        
	public CategoriaTreeModel(List&lt;Categorias&gt; categorias) {
	    this.categorias = categorias;
            
            //Se a categoria é vazia(adiciona a raiz nela)
            if (categorias.isEmpty())
            {
                categorias.add(fakeRoot);
            }
	}

	/**
	 * Com esse método, o Java quem é o objeto que está num determinado índice
	 * do pai. Cada nó de uma árvore pode ser encarado como uma lista. Sendo o
	 * pai a lista e o índice um dos filhos.
	 *
	 * @param parent
	 *            É o pai, que tem os filhos. No caso do Livro, o próprio livro.
	 * @param index
	 *            Índice do filho. No caso do livro, o índice corresponde aos
	 *            autores.
	 */
        @Override
	public Object getChild(Object parent, int index) {
                
//		if (parent == fakeRoot) // É o nó principal?
//			return categorias.get(index); // Pegamos da lista de livro

		if (parent instanceof Categorias) // O pai é uma categoria?
		{
			//List&lt;Categorias&gt; cat = categorias;
			if (index &lt; ((Categorias) parent).getSubCategorias().size()) {
				return ((Categorias) parent).getSubCategorias().get(index);
			}  
                        
                            return ((Categorias) parent).getItens().get(index - ((Categorias) parent).getSubCategorias().size()); // Se não lista os itens(filhos)
               }
            return null;
	}

	/**
	 * Retornamos quantos filhos um pai tem. No caso de um livro, é a contagem
	 * de autores. No caso da lista de livros, é a quantidade de livros.
	 */
        @Override
	public int getChildCount(Object parent) {
		// Mesma lógica.
//		if (parent == fakeRoot)
//			return categorias.size();

		if (parent instanceof Categorias) {
			Categorias cat = (Categorias) parent;
			return cat.getSubCategorias().size() + cat.getItens().size();
		}
            return 0;
	}

	/**
	 * Dado um pai, indicamos qual é o índice do filho correspondente.
	 */
        @Override
	public int getIndexOfChild(Object parent, Object child) {
		//if (parent == fakeRoot)
		//	return categorias.indexOf(child);
		if (parent instanceof Categorias) {
			if (child instanceof Categorias)
			     return ((Categorias) parent).getSubCategorias().indexOf(child);
                        
			return ((Categorias) parent).getSubCategorias().size() + ((Categorias) parent).getItens().indexOf(child);
		}

		return 0;
	}

	/**
	 * Devemos retornar quem é o nó raiz da árvore. Afinal, a árvore tem que
	 * começar em algum lugar.
	 */
        @Override
	public Object getRoot() {
		return fakeRoot;
	}

	/**
	 * Indicamos se um nó é ou não uma folha. Isso é, se ele não tem filhos. No
	 * nosso caso, os autores são as folhas da árvore.
	 */
        @Override
	public boolean isLeaf(Object node) {

                return node instanceof Itens;
	}
        
        public void adicionarLivro(Categorias livro)
        {
            categorias.add(livro);
            fireLastPathComponentInserted(fakeRoot, livro);
        }

        public void adicionarCategoria(Categorias _categSelecionada, Categorias _categoria)
        {
            
            Categorias categAdd = percorreCategorias(categorias, _categSelecionada);
            categAdd.addSubCategoria(_categoria);
            
            //monta o caminho para exibição do treeview
            fireLastPathComponentInserted(montaPath(_categoria, null));
        }        
        
        //Percorre recursivamente o ArrayList Categorias
        //retornando a classe selecionada
        public Categorias percorreCategorias(List&lt;Categorias&gt; arrCategorias, Categorias livroSelecionado)
        {
            Categorias retorno = null;
            //Percorre o arraylist para adicionar as novas categorias
            for (int i = 0; i &lt; arrCategorias.size(); i++)
            {
                if (arrCategorias.get(i) == livroSelecionado)
                {
                        retorno = arrCategorias.get(i);
                        if(retorno != null)
                        {
                            return retorno;
                        }                        
                }else{

                    if(arrCategorias.get(i).getSubCategorias().size() &gt; 0)
                    {
                        retorno = percorreSubCategorias(arrCategorias.get(i), livroSelecionado);
                        if(retorno != null)
                        {
                            return retorno;
                        }                        
                    }
                }
            } 
            return retorno;
        }
        
        //Metodo para percorrer recursivamente as subcategorias do ArrayList categorias 
        //para adicionar as novas categorias no Array
        public Categorias percorreSubCategorias(Categorias categI, Categorias livroSelecionado)
        {
            Categorias retorno;
            for (int i = 0; i &lt; categI.getSubCategorias().size(); i++)
            {
                if (categI.getSubCategorias().get(i) == livroSelecionado)
                {
                        retorno = categI.getSubCategorias().get(i);
                        if(retorno != null)
                        {
                            return retorno;
                        }
                }else{

                    if(categI.getSubCategorias().get(i).getSubCategorias().size() &gt; 0)
                    {
                        retorno = percorreSubCategorias(categI.getSubCategorias().get(i), livroSelecionado);
                        if(retorno != null)
                        {
                            return retorno;
                        }                        
                    }
                }
            }
            return null;
        }
        
        public void adicionarItem(Categorias _categorias, Itens _item)
        {
            _categorias.addItem(_item);
            fireLastPathComponentInserted((Object[])montaPath(null, _item));
        }
        
        public void remover( Object itemSelecionado)
        {
            if(itemSelecionado instanceof Categorias)
            {
                //Monta o Path para notificar a exclusão do nó
                Object[] objPath = montaPath((Categorias)itemSelecionado, null);
                TreePath path =  new TreePath(objPath);
                Object parent = path.getParentPath().getLastPathComponent();
                
                //Notifica a exclusão do nó
                fireLastPathComponentRemoved(objPath);
                
                //Retorna a classe do pai do objeto selecionado
                //para excluir o objeto selecionado
                Categorias teste = percorreCategorias(categorias, (Categorias)parent);
                //teste.getSubCategorias().remove((Categorias)itemSelecionado);
                teste.removeSubCategoria((Categorias)itemSelecionado);

            }
            
            if(itemSelecionado instanceof Itens)
            {
                //Monta o Path para notificar a exclusão do nó
                Object[] objPath = montaPath(null, (Itens)itemSelecionado);
                TreePath path =  new TreePath(objPath);
                Object parent = path.getParentPath().getLastPathComponent();
                
                //Notifica a exclusão do nó
                fireLastPathComponentRemoved(objPath);
                
                //Retorna a classe do pai do objeto selecionado
                //para excluir o objeto selecionado
                Categorias teste = percorreCategorias(categorias, (Categorias)parent);
                //teste.getSubCategorias().remove((Categorias)itemSelecionado);
                teste.removeItens((Itens)itemSelecionado);

            }            

        }

        
        //Método para percorrer o ArrayList categorias para montar o Path do menu selecionado
        //public Object[] montaPath(Object sel)
        public Object[] montaPath(Categorias _categoriaProcurada, Itens _item)
        {
            Object[] retorno = new Object[0];
            
            if(_categoriaProcurada != null)
            {
                for(Categorias categs : categorias)
                {
                    if(categs.getSubCategorias().size() &gt; 0)
                    {
                        List&lt;Categorias&gt; arrVarreSub = (List&lt;Categorias&gt;) varreSub(categs, _categoriaProcurada, null);
                        if (arrVarreSub != null)
                        {

                            for(Categorias retVarre : arrVarreSub)
                            {
                                int ictrl = retorno.length;
                                retorno = (Object[]) resizeArray(retorno, retorno.length + 1);
                                retorno[ictrl] = retVarre;                               
                            }

                            return retorno;
                        }
                    }
                }
            }
            
            if(_item != null){
                
                for(Categorias categs : categorias)
                {
                    //Percorre os itens na raiz
                    for(Itens item : categs.getItens())
                    {
                        //Se o item for igual 
                        if(item == _item)
                        {
                            retorno = (Object[]) resizeArray(retorno, retorno.length + 1);
                            retorno[retorno.length - 1] = categs;       
                            
                            retorno = (Object[]) resizeArray(retorno, retorno.length + 1);
                            retorno[retorno.length -1] = item;
                            return retorno;
                        }
                        
                    }
                    if(categs.getSubCategorias().size() &gt; 0)
                    {
                        List&lt;Object&gt; arrVarreSub = (List&lt;Object&gt;) varreSub(categs, null, _item);
                        if (arrVarreSub != null)
                        {
                            for(Object obj : arrVarreSub)
                            {
                                retorno = (Object[]) resizeArray(retorno, retorno.length + 1);
                                retorno[retorno.length -1] = obj;                       
                            }
                            return retorno;
                        }
                    }
                }
                
            }
        return null;
        }
        
        public Object retornaPath(Object teste)
        {
            return new TreePath(teste);
        }
        
        public Object varreItens(Categorias _categorias, Itens _itemSel)
        {
            for(Itens itens : _categorias.getItens())
            {
                if (itens == _itemSel)
                {
                    return itens;
                }
                
            }
            
            return null;
        }
        
        public Object varreSub(Categorias _categorias, Object _categSel, Itens _itemSel)
        {
            List&lt;Object&gt; retorno = new ArrayList();

                retorno.add(_categorias);


                for (Categorias categs : _categorias.getSubCategorias())
                {
                    retorno.add(categs);
                    
                    for(Itens _item : categs.getItens())
                    {
                        if(_item == _itemSel)
                        {
                            retorno.add(_item);
                            return retorno; 
                        }
                    }
                    retorno.remove(categs);
                    
                    if(categs == _categSel)
                    {
                        retorno.add(categs);
                        return retorno;
                    }

                    if(categs.getSubCategorias().size() &gt; 0)
                    {
                        for (Categorias _categs : categs.getSubCategorias())
                        {
                            retorno.add(categs);

                            for(Itens _item : _categs.getItens())
                            {
                                retorno.add(_categs);
                                if(_item == _itemSel)
                                {
                                    retorno.add(_item);
                                    return retorno; 
                                }
                                retorno.remove(_categs);
                            }                            

                            if(_categs == _categSel)
                            {
                                retorno.add(_categs);
                                return retorno;
                            }

                            if(_categs.getSubCategorias().size() &gt; 0)
                            {
                                List&lt;Object&gt; arrVarreSub = (List&lt;Object&gt;) varreSub(_categs, (Categorias) _categSel, _itemSel);
                                if (arrVarreSub != null)
                                {
                                    for(Object retVarre : arrVarreSub)
                                    {
                                       retorno.add(retVarre);
                                    }
                                    return retorno;
                                }
                            }

                            retorno.remove(categs);
                        }
                    }
                }
                return null;
            }

        //Percorre as subcategorias da tree recursivamente
        public Object varreSubCateg(Categorias categ, Categorias categSel)
        {
            List&lt;Object&gt; retorno = new ArrayList();
            
            for(Categorias categs : categ.getSubCategorias())
            {
                if(categs == categSel)
                {
                    retorno.add(categ);
                    retorno.add(categs);
                    return retorno;
                }
                
                if(categs.getSubCategorias().size() &gt; 0)
                {
                    List&lt;Categorias&gt; arrVarreSub = (List&lt;Categorias&gt;) varreSubCateg(categs, (Categorias) categSel);
                    if (arrVarreSub != null)
                    {
                        retorno.add(categ);
                        for(Categorias retVarre : arrVarreSub)
                        {
                           retorno.add(retVarre);
                        }
                        return retorno;
                    }
                }
            }           
            return null;
        }
        
        private static Object resizeArray (Object oldArray, int newSize) {
            int oldSize = java.lang.reflect.Array.getLength(oldArray);
            Class elementType = oldArray.getClass().getComponentType();
            Object newArray = java.lang.reflect.Array.newInstance(elementType, newSize);
            int preserveLength = Math.min(oldSize, newSize);
            if (preserveLength &gt; 0)
               System.arraycopy(oldArray, 0, newArray, 0, preserveLength);
            return newArray; 
        }
}
Criado 15 de outubro de 2008
Ultima resposta 31 de jul. de 2013
Respostas 21
Participantes 5