Como usar JTree

23 respostas
cleiton_herrmann

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

davidbuzatto

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!

cleiton_herrmann

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?

cleiton_herrmann

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+

luis.txt

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

}
ViniGodoy

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.

luis.txt

com o seu exemplo realmente ficou muito melhor!

valeu!

lidianycs

Muito interessante seu exemplo!
Obrigada!

hacebe

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:

ViniGodoy

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?

ViniGodoy

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:

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?

R

Não sei como escrever o treemodel.

ViniGodoy

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…

sfidencio

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

ViniGodoy

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