Como usar JTree

23 respostas
C

Olá Pessoal, essa dúvida pode parecer meio simples para se perguntar no grupo de tópicos Avançados, porém, eu já peguei 6 exemplos de como usar o JTree e não consegui usar.

Eu uso o NetBeans 5.0, será que alguem sabe alguma maneira prática de usar esse componente, alguma maneira de manipular ele graficamente no NetBeans, ou mesmo um exemplo da criação e manipulação de um JTree.

Desde já grato !!!

23 Respostas

D

kra, vc num vai conseguir manipular um jtree graficamente como vc disse.

da uma olhada na documentação na class JTree e no pacote javax.swing.tree q vc vai achar o q precisa.

caso não consiga fazer nada, posta ai o q vc quer fazer q a gente ajuda :smiley:

falow!

C

Olá davidbuzatto, blz?

na verdade o que eu queria é um exemplo simples da utilização do JTree, criando uma estrutura simples tipo
+ Nivel 1
   + asdasfd
   + asdfasf
+ Nivel 2
   + asdasf
   + asdfaf
uma coisa bem simples mesmo, pois nunca trabalhei com esse componente. vc tinha sugerido pra eu olhar a documentacao, mas o exemplo que tem lah é muito grande, nao sei, eu coloco aqueles DefaultMutableTreeNode, faço meu Jtree = new Jtree(o node que eu criei) i nao consigo fazer funcionar, sei lah haiuhaiaaiha. Ó, eu to fazendo assim ó

eu uso o NetBeans, dai eu arrastei um JTree pra minha tela, dei um nome pra ele de jtInformacoes, ai no construtor da classe, depois do initComponents eu coloquei o codigo seguinte só pra testar

DefaultMutableTreeNode top = new DefaultMutableTreeNode("Nível 1");
top.add(new DefaultMutableTreeNode("asdfasdf"));
jtInformacoes = new JTree(top);
mas ai quando eu rodo a aplicacao, aparece o JTree original na tela, sem nenhuma modificação.

o que eu queria mesmo é só um exemplo simples pra eu entender como funciona, se vc ou alguem puder postar um codigozinhu ai eu agradeco, pois jah faz 3 dias que to tentando usar esse componente e nada.

valeu t+

H

olha este site da sun: http://java.sun.com/docs/books/tutorial/uiswing/components/tree.html

e ai ajudou?

C

Olá pessoal, td bom?

Ainda nao consegui fazer funcionar, vou colocar o meu código ai, pq eu sinceramente nao sei o q q tah faltando. No construtor da minha tela, eu faço

jScrollPane2.setViewportView(null);

e no evento MouseClicked da minha tabela eu chamo esse método preencherJTree();

private void preencherJTree() {
        int linha = jtInfo.getSelectedRow() + 1;//recebe a posicao da linha selecionada na tabela + 1
        p =  (Packet) pacotes.elementAt(linha);pega o objeto do vetor que corresponde ao objeto selecionado na tabela
        DefaultMutableTreeNode pacote = new DefaultMutableTreeNode("Informações do pacote);
        
        DefaultMutableTreeNode dataCaptura = new DefaultMutableTreeNode("Data da captura: " + p.sec);
        DefaultMutableTreeNode tamPacote = new DefaultMutableTreeNode("Tamanho do pacote: " + p.len);
        pacote.add(dataCaptura);
        pacote.add(tamPacote);
         jtInformacoes = new JTree(pacote);
        
        jtInformacoes.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
            public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
                jtInformacoesValueChanged(evt);
            }
        });
        jScrollPane2.setViewportView(jtInformacoes); 
    }

ai quando eu rodo minha aplicacao e clico em uma linha da tabela, nao acontece nada, nem da erro, neim aparece nada no jtInformacoes, que é o meu objeto JTree…
Nos exemplos que vi na internet, e no How to use da sum, eu nao vejo nada de diferente, eu simplesmente adaptei o exemplo de acordo com minhas necessidades, mas nao funciona. O que será que está faltando pra isso ai funcionar?
Desde ja meu obrigado, t+

L

Bem, também tive dificuldade para encontrar um exemplo de uso do JTree.
Por isso resolvi postar aqui a solução que encontrei..
Há outros objetos gráficos na classe, mas eu resolvi postar toda a estrutura, fica melhor compreendido, principalmente depois de compilado::

//Classe que inicializa a aplicação:

public class Runner {

	public static void main(String[] args) {
		FTPPrincipalView view = new FTPPrincipalView();
		
	}

}
//Classe que implementa o JTree (APENAS IMPLEMENTA O JTREE, CABE A VC IMPLEMENTAR AS FUNCIONALIDADES)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Point;
import java.awt.Rectangle;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTree;
import javax.swing.SwingConstants;
import javax.swing.border.Border;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;

public class FTPPrincipalView {

	private JFrame _jFrameFTP = null;  
	private JPanel _jContentPaneFTP = null;
	private JPanel _jPanelCenter = null;
	private JLabel _jLabelTreeFTP = null;
	private JTree _jTreeFTP = null;
	private JLabel _jLabelArquivos = null;
	private JLabel _jLabelTitulo = null;
	private DefaultMutableTreeNode _top = null;
	
	public FTPPrincipalView(){
		init();		
	}
	public void init() {
		_top = new DefaultMutableTreeNode();
		createNodes();
	    get_jFrameFTP();
		_jFrameFTP.setVisible(true);
		
	}
	private JFrame get_jFrameFTP() {
		if (_jFrameFTP == null) {
			_jFrameFTP = new JFrame();
			_jFrameFTP.setTitle("FTP Cliente");
			_jFrameFTP.setName("_jFrameFTP");
			_jFrameFTP.setPreferredSize(new Dimension(800, 700));
			_jFrameFTP.setLocation(new Point(0, 0));
			_jFrameFTP.setSize(new Dimension(800, 600));
			_jFrameFTP.setVisible(true);
			_jFrameFTP.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			_jFrameFTP.setContentPane(get_jContentPaneFTP());
		}
		return _jFrameFTP;
	}

	
	private JPanel get_jContentPaneFTP() {
		if (_jContentPaneFTP == null) {
			_jLabelTitulo = new JLabel();
			_jLabelTitulo.setBounds(new Rectangle(203, 10, 168, 26));
			_jLabelTitulo.setFont(new Font("Garamond", Font.BOLD, 24));
			_jLabelTitulo.setForeground(new Color(51, 51, 255));
			_jLabelTitulo.setHorizontalTextPosition(SwingConstants.CENTER);
			_jLabelTitulo.setHorizontalAlignment(SwingConstants.CENTER);
			_jLabelTitulo.setText("FTP Cliente");
			_jContentPaneFTP = new JPanel();
			_jContentPaneFTP.setLayout(null);
			_jContentPaneFTP.add(get_jPanelCenter(), null);
			_jContentPaneFTP.add(_jLabelTitulo, null);
			_jContentPaneFTP.updateUI();
		}
		return _jContentPaneFTP;
	}

	private JPanel get_jPanelCenter() {
		if (_jPanelCenter == null) {
			_jLabelArquivos = new JLabel();
			_jLabelArquivos.setBounds(new Rectangle(181, 26, 97, 16));
			_jLabelArquivos.setText("Arquivos:");
			_jLabelTreeFTP = new JLabel();
			_jLabelTreeFTP.setText("Árvore de Diretórios:");
			_jLabelTreeFTP.setBounds(new Rectangle(20, 26, 125, 16));
			_jPanelCenter = new JPanel();
			_jPanelCenter.setLayout(null);
			_jPanelCenter.setPreferredSize(new Dimension(200, 200));
			_jPanelCenter.setBounds(new Rectangle(6, 187, 450, 269));
			_jPanelCenter.add(_jLabelTreeFTP, null);
			_jPanelCenter.add(get_jTreeFTP(), null);
			_jPanelCenter.add(_jLabelArquivos, null);
			Border borderPanelCenter = BorderFactory.createRaisedBevelBorder();
			Border tituloPanelCenter = BorderFactory.createTitledBorder(borderPanelCenter,"Árvore FTP: ");
			_jPanelCenter.setBorder(tituloPanelCenter);
			
		}
		return _jPanelCenter;
	}
	
	private JTree get_jTreeFTP() {
		if (_jTreeFTP == null) {
			_jTreeFTP = new JTree(_top);
			_jTreeFTP.setBounds(new Rectangle(12, 46, 155, 210));
			_jTreeFTP
					.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
						public void valueChanged(javax.swing.event.TreeSelectionEvent e) {
							System.out.println("valueChanged()"); // TODO Auto-generated Event stub valueChanged()
						}
					});
			
		}
		_jTreeFTP.getSelectionModel().setSelectionMode
        (TreeSelectionModel.SINGLE_TREE_SELECTION);

//Listen for when the selection changes.
		_jTreeFTP.addTreeSelectionListener(new TreeSelectionListener(){
			public void valueChanged(TreeSelectionEvent e) {
				//Returns the last path element of the selection.
				//This method is useful only when the selection model allows a single selection.
				    DefaultMutableTreeNode node = (DefaultMutableTreeNode)
				                       _jTreeFTP.getLastSelectedPathComponent();
				    createNodes();
				    if (node == null)
				    //Nothing is selected.	
				    return;

				    Object nodeInfo = node.getUserObject();
				    if (node.isLeaf()) {
				       // BookInfo book = (BookInfo)nodeInfo;
				      //  displayURL(book.bookURL);
				    } else {
				       // displayURL("javafor.web44.net"); 
				    }
				}

		});

		return _jTreeFTP;
	}



	private void createNodes() {
	    DefaultMutableTreeNode category = null;
	    DefaultMutableTreeNode book = null;
	    
	    category = new DefaultMutableTreeNode("Teste1");
	    _top.add(category);
	    
	   
	    book = new DefaultMutableTreeNode("Tutorial");
	    category.add(book);
	    
	    book = new DefaultMutableTreeNode("Tutorial2");
	    category.add(book);
	   
	    book = new DefaultMutableTreeNode("The Tutorial");
	    category.add(book);

	    category = new DefaultMutableTreeNode("Linguagem");
	    
	    book = new DefaultMutableTreeNode("Linguagem C");
	    category.add(book);

	    book = new DefaultMutableTreeNode("Java");
	    category.add(book);
	    
	    _top.add(category);
	}
	

}
V

Ao invés de usar o DefaultMutableTreeNode, criem um TreeModel próprio.
É muito mais fácil.

Considerem uma classe de Livros, que contém uma lista de autores, como essa aqui:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Livro {
	private String nome;
	private List<Autor> autores = new ArrayList<Autor>();

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

	public String getNome() {
		return nome;
	}

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

	public void addAutor(Autor autor) {
		autores.add(autor);
	}

	public List<Autor> getAutores() {
		return Collections.unmodifiableList(autores);
	}
}
A classe do Autor não é muito diferente:
public class Autor {
	private String nome;

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

	public String getNome() {
		return nome;
	}

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

Ok. Agora queremos uma árvore com vários livros e a lista dos seus autores. O primeiro passo, é criar um modelo para essa árvore. Fazemos isso estendendo TreeModel:

import java.util.ArrayList;
import java.util.List;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

public class LivroTreeModel implements TreeModel {
        //Criamos um objeto para nossa raiz. O List não pode ser usado diretamente pois
        //seu hash irá mudar sempre que um novo livro for adicionado.
        //Fora que é mais bonitinho escrever "Livros" no topo.
        private String raiz = "Livros";

	// Escrevam depois AbstractTreeModel para lidar com os listeners.
	private List<TreeModelListener> listeners = new ArrayList<TreeModelListener>();

	// Raiz da nossa árvore, vamos exibir uma lista de livros.
	private List<Livro> livros;

	public LivroTreeModel(List<Livro> 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 == raiz) // É o nó principal?
			return livros.get(index); // Pegamos da lista de livro

		if (parent instanceof Livro) // O pai é um livro?
		{
			// Devolvemos um autor
			return ((Livro) parent).getAutores().get(index);
		}

		// 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 == raiz)
			return livros.size();

		if (parent instanceof Livro) // O pai é um livro?
			return ((Livro) parent).getAutores().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 == raiz)
			return livros.indexOf(child);
		if (parent instanceof Livro)
			return ((Livro) parent).getAutores().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 raiz;
	}

	/**
	 * 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 Autor;
	}

	public void valueForPathChanged(TreePath path, Object newValue) {
		// Com esse método, a tree avisa que um objeto mudou.
		// Editem se quiserem que um nó seja editável
	}

	// Esses dois métodos abaixo poderiam ir para classe abstrata
	public void removeTreeModelListener(TreeModelListener l) {
		listeners.remove(l);
	}

	public void addTreeModelListener(TreeModelListener l) {
		listeners.add(l);
	}
}
Com o model pronto, agora só falta desenhar uma Tree usando esse model. Aqui está uma telinha que faz exatamente isso, para servir de demonstração:
import java.awt.BorderLayout;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.TreeModel;

public class Tela extends JDialog {
	private static final long serialVersionUID = 1L;
	private JPanel jContentPane = null;
	private JScrollPane scrlTree = null;
	private JTree treeLivros = null;
	private TreeModel treeModel;

	public Tela(TreeModel treeModel) {
		super();
		this.treeModel = treeModel;
		initialize();
	}

	private void initialize() {
		this.setSize(361, 240);
		this.setLocationRelativeTo(null);
		this.setTitle("Tree");
		this.setContentPane(getJContentPane());
		this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
	}

	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getScrlTree(), BorderLayout.CENTER);
		}
		return jContentPane;
	}

	private JScrollPane getScrlTree() {
		if (scrlTree == null) {
			scrlTree = new JScrollPane();
			scrlTree.setViewportView(getTreeLivros());
		}
		return scrlTree;
	}

	private JTree getTreeLivros() {
		if (treeLivros == null) {
			treeLivros = new JTree(treeModel);
			treeLivros.setRootVisible(false);
			treeLivros.setShowsRootHandles(true);
		}
		return treeLivros;
	}

	public static void main(String[] args) {
		List<Livro> livros = new ArrayList<Livro>();

		Livro livro = new Livro("Duna");
		livro.addAutor(new Autor("Frank Herbert"));
		livros.add(livro);

		Livro livro2 = new Livro("50 Anos Depois");
		livro2.addAutor(new Autor("Chico Xavier"));
		livro2.addAutor(new Autor("Emmanuel (Espírito)"));
		livros.add(livro2);

		Livro livro3 = new Livro("O rapto do garoto de ouro");
		livro3.addAutor(new Autor("Marcos Rey"));
		livros.add(livro3);

		Tela tela = new Tela(new LivroTreeModel(livros));
		tela.setVisible(true);
	}
}

Escrever o seu próprio TreeModel não só é mais fácil para Trees maiores, como também deixa o código mais separado e orientado a objetos. Note que a minha classe de interface gráfica praticamente não se preocupou com a lógica da tree em si. Quem faz isso é o modelo. Esse decoplamento é util, caso você queira reaproveitar a tree em outras telas, já que não é a tela em si que conhece a estrutura da árvore.

Também tem a vantagem de que o TreeModel manipula diretamente as suas classes de negócio. Para tornar a Tree modificável, você deve inserir métodos no model, e notificar os listeners de que a árvore mudou, e onde. Anexo a esse post, está um AbstractTreeModel que costumo a usar nos meus programas, retirado dos próprios exemplos da Sun.

Ele já cuida da parte dos listeners de eventos, além de fornecer métodos práticos para notificar a tree sobre mudanças.

A minha sugestão (e eu já sofri muito da outra forma antes de descobrir essa) é que vocês não usem os DefaultMutableTreeNodes para nada.

L

com o seu exemplo realmente ficou muito melhor!

valeu!

L

Muito interessante seu exemplo!
Obrigada!

H

Opa… bom dia!

resuscitando um pouco o tópico…

Pessoal, fiz o código deu certim…
ele aparece e talz…

mas tipo

se eu quiser repopular essa tree, como faço?

grato! :smiley:

V

Basta passar um novo List para o seu model, e disparar o evento que os dados da tree mudaram.

R

Rodei o exempo assim, porem tenho uma dúvida: Tendo 2 tree(arvoreA e arvoreB) como fazer para mover uma “folha” da arvoreA para a arvoreB?

V

Sua dúvida está em manipular modelos ou em fazer a movimentação em si?

R

Gostaria de mover de uma estrutura para outra, ou seja:

1° Mometo
arvoreA

  • Nivel A
    • Item 1
    • Item 2
      -Nivel B
    • Item 1

arvoreB

  • Nivel C
    • Item 1
    • Item 2

2° Momento: após arrastar o “Nivel B” da arvoreA para o “Nivel C” da arvore B o resultado ficaria
arvoreA

  • Nivel A
    • Item 1
    • Item 2

arvoreB

  • Nivel C
    • Item 1
    • Item 2
    • Nivel B
      • Item 1

resultado toda estrutura foi copiada para baixo do “Nivel C” da arvoreB.

Valeu pela rapidez da resposta, muito obrigado :lol:

V

Ótimo… mas voltando a minha pergunta…

Sua dúvida está em manipular modelos ou em fazer a movimentação em si?

Ou seja, você não sabe como escrever o treemodel, ou você não sabe como habilitar o drag&drop?

R

Não sei como escrever o treemodel.

V

Você conseguiu entender o exemplo anterior? Se não conseguiu o que ficou faltando?

R

Bem, para minha pouca pratica com Java até que deu para entender. Tenho tambem estudado os exemplos desse link (http://java.sun.com/docs/books/tutorial/uiswing/components/tree.html) porem não encontrei um local que me mostre os eventos do JTree, ou seja, arrastar, poder selecionar mais de um nó, etc.

Obrigado mais uma vez…

S

Desculpa ai…ressucitar esse tópico, mas como eu implementaria o controle de acesso de um sistema.? ou seja, o usuario X terá acesso a isso,isso e isso… usando Jtree?

Como que eu faço para Realizar Crud NO jTREE…?

T

ViniGodoy:
Ótimo… mas voltando a minha pergunta…

Sua dúvida está em manipular modelos ou em fazer a movimentação em si?

Ou seja, você não sabe como escrever o treemodel, ou você não sabe como habilitar o drag&drop?

Aproveitando esta sua mensagem!
Eu tenho duvidas em escrever o treeModel, não entendi bem a parte do parent e da raiz, no funfo como funciona a estrutura de armazenamento na treeModel!
O que pretendo fazer é utilizar datas para organizar eventos do género:

12/6/2011
-> Exame Final
-> Final das Aulas

14/06/2011
->Saida de campo
->Feriado Nacional

DEsde já um muito obrigado pela atenção

D

Vini, como eu faria para selecionar o nó “Frank Herbert” e abrir um JInternalFrame ?

Essa alteração eu faria no meu modelo de árvore ?

Obrigado

V

Isso você faz pelos eventos de seleção normalmente, como faria se usasse um DefaultMutableTreeNode.

A

Boa noite gente,
Alguém poderia me dizer como por o checkbox na jtree?
Fiz meu model de acordo com o que o vini passou, falta entender como por o checkbox.
Grata

B

Vini, Desculpe estar desenterrando esses tópicos, mas eu estou com a dúvida do amigo aí em cima, manipular os modelos já peguei o macete… minha dúvida está em movimentar os ’ Nós ’ utilizando o modelo do exemplo acima, procurei na net mas achei muito confuso não estou conseguindo assimilar a parada, se você poder me ajudar te agradeço, pode ser em cima do exemplo que você deu mesmo, a idéia é mover as folhas entre os nós…

Criado 25 de julho de 2006
Ultima resposta 6 de ago. de 2013
Respostas 23
Participantes 13