Como usar JTree

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 !!!

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!

Olá davidbuzatto, blz?

na verdade o que eu queria é um exemplo simples da utilização do JTree, criando uma estrutura simples tipo

[code]

  • Nivel 1
    • asdasfd
    • asdfasf
  • Nivel 2
    • asdasf
    • asdfaf[/code]
      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+

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

e ai ajudou?

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+

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:

[code]public class Runner {

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

}[/code]
//Classe que implementa o JTree (APENAS IMPLEMENTA O JTREE, CABE A VC IMPLEMENTAR AS FUNCIONALIDADES)

[code]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);
}

}[/code]

1 curtida

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:

[code]
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&lt;Autor&gt; getAutores() {
	return Collections.unmodifiableList(autores);
}

}[/code]

A classe do Autor não é muito diferente:

[code]
public class Autor {
private String nome;

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

public String getNome() {
	return nome;
}

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

}[/code]

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:

[code]
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&lt;TreeModelListener&gt; listeners = new ArrayList&lt;TreeModelListener&gt;();

// Raiz da nossa árvore, vamos exibir uma lista de livros.
private List&lt;Livro&gt; livros;

public LivroTreeModel(List&lt;Livro&gt; 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);
}

}[/code]

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:

[code]
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&lt;Livro&gt; livros = new ArrayList&lt;Livro&gt;();

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

} [/code]

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.

3 curtidas

com o seu exemplo realmente ficou muito melhor!

valeu!

Muito interessante seu exemplo!
Obrigada!

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:

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

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?

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

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:

Ó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?

Não sei como escrever o treemodel.

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

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…

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…?

[quote=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?[/quote]

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