Exemplo Tree com CheckBox utilizando TreeModel

Ei galera, depois de estudar bastante o exemplo do Viny Godoi onde o mesmo aconselha a usar TreeModel para montar uma Tree e depois de estudar como adicionar CheckBox à mesma e tratar seus eventos, crie esse exemplo que pode auxiliar alguém que esteja precisando…

Se encontrarem algo a ser melhorado e talvez corrigido peço que postem por favor, isso me ajudará também a aprender um pouco mais
:slight_smile:

Espero que ajude alguém…

Carro .java

[code]package treemodelexample.bean;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.swing.tree.DefaultMutableTreeNode;

public class Carro extends DefaultMutableTreeNode{

private Long id;
private String nome;
private List<Pessoa> pessoas;
private Boolean selected= false;
public final static int DIG_IN_SELECTION = 4;
protected int selectionMode;
protected boolean isSelected;

public Carro() {
    pessoas = new ArrayList<Pessoa>();
}

public Carro(Long id, String nome, List<Pessoa> pessoas) {
    this.id = id;
    this.nome = nome;
    this.pessoas = pessoas;
}

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public String getNome() {
    return nome;
}

public void setNome(String nome) {
    this.nome = nome;
}

public List<Pessoa> getPessoas() {
    return pessoas;
}

public void setPessoas(List<Pessoa> pessoas) {
    this.pessoas = pessoas;
}

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

public void getSelected(Boolean selected){
    this.selected = selected;
}

    public void setSelectionMode(int mode) {
    selectionMode = mode;
}

public int getSelectionMode() {
    return selectionMode;
}

public void setSelected(boolean isSelected) {
    this.isSelected = isSelected;

    if ((selectionMode == DIG_IN_SELECTION)
            && (children != null)) {
        Enumeration menum = children.elements();
        while (menum.hasMoreElements()) {
            Pessoa node = (Pessoa) menum.nextElement();
            node.setSelected(isSelected);
        }
    }
}

public boolean isSelected() {
    return isSelected;
}

}
[/code]
Fabrica .java

[code]package treemodelexample.bean;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.swing.tree.DefaultMutableTreeNode;

public class Fabrica extends DefaultMutableTreeNode{

private Long id;
private String nome;
private List<Carro> carros;
private Boolean selected = false;
public final static int DIG_IN_SELECTION = 4;
protected int selectionMode;
protected boolean isSelected;

public Fabrica(Long id, String nome, List<Carro> carros) {
    this.id = id;
    this.nome = nome;
    this.carros = carros;
}

public Fabrica() {
    carros = new ArrayList<Carro>();
}

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public String getNome() {
    return nome;
}

public void setNome(String nome) {
    this.nome = nome;
}

public List<Carro> getCarros() {
    return carros;
}

public void setCarros(List<Carro> carros) {
    this.carros = carros;
}

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

public void getSelected(Boolean selected){
    this.selected = selected;
}

    public void setSelectionMode(int mode) {
    selectionMode = mode;
}

public int getSelectionMode() {
    return selectionMode;
}

public void setSelected(boolean isSelected) {
    this.isSelected = isSelected;

    if ((selectionMode == DIG_IN_SELECTION)
            && (children != null)) {
        Enumeration menum = children.elements();
        while (menum.hasMoreElements()) {
            Carro node = (Carro) menum.nextElement();
            node.setSelected(isSelected);
        }
    }
}

public boolean isSelected() {
    return isSelected;
}

}
[/code]
Pessoa .java

[code]package treemodelexample.bean;

import javax.swing.tree.DefaultMutableTreeNode;

public class Pessoa extends DefaultMutableTreeNode{

private Long id;
private String nome;
private Boolean selected=true;
public final static int DIG_IN_SELECTION = 4;
protected int selectionMode;
protected boolean isSelected;

public Pessoa() {
}

public Pessoa(Long id, String nome) {
    this.id = id;
    this.nome = nome;
}

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public String getNome() {
    return nome;
}

public void setNome(String nome) {
    this.nome = nome;
}

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

public void getSelected(Boolean selected){
    this.selected = selected;
}

    public void setSelectionMode(int mode) {
    selectionMode = mode;
}

public int getSelectionMode() {
    return selectionMode;
}

public void setSelected(boolean isSelected) {
    this.isSelected = isSelected;
}

public boolean isSelected() {
    return isSelected;
}

}
[/code]
Tela .java

[code]/*

  • To change this license header, choose License Headers in Project Properties.
  • To change this template file, choose Tools | Templates
  • and open the template in the editor.
    */

package treemodelexample;

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;
import treemodelexample.bean.Carro;
import treemodelexample.bean.Fabrica;
import treemodelexample.bean.Pessoa;

public class Tela extends JDialog {
private static final long serialVersionUID = 1L;
private JPanel jContentPane = null;
private JScrollPane scrlTree = null;
private JTree treeFabricas = 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 (treeFabricas == null) {  
        treeFabricas = new JTree(treeModel);  
        treeFabricas.setCellRenderer(new CheckRenderer());
        treeFabricas.addMouseListener(new NodeSelectionListener(treeFabricas));
        treeFabricas.setRootVisible(false);  
        treeFabricas.setShowsRootHandles(true);  
    }  
    return treeFabricas;  
}  

public static void main(String[] args) {  
    Pessoa p1 = new Pessoa(1L,"João Silva");
    Pessoa p2 = new Pessoa(2L,"Pedro Silva");
    Pessoa p3 = new Pessoa(3L,"Mônica Silva");
    Pessoa p4 = new Pessoa(4L,"Diogo Silva");
    Pessoa p5 = new Pessoa(5L,"Raphael Silva");
    Pessoa p6 = new Pessoa(6L,"Breno Silva");
    Pessoa p7 = new Pessoa(7L,"Kathyucia Silva");
    Pessoa p8 = new Pessoa(8L,"Pedro Silva");
    Pessoa p9 = new Pessoa(9L,"Arnaldo Silva");
    Pessoa p10 = new Pessoa(10L,"Bruno Silva");
    Pessoa p11 = new Pessoa(9L,"Amarildo Silva");
    Pessoa p12 = new Pessoa(10L,"Marcia Silva");
    
    Carro c1 = new Carro();
    c1.setId(1L);
    c1.setNome("Fiesta");
    c1.getPessoas().add(p1);
    c1.getPessoas().add(p2);
    
    
    Carro c2 = new Carro();
    c2.setId(2L);
    c2.setNome("Uno");
    c2.getPessoas().add(p3);
    c2.getPessoas().add(p4);
    c2.getPessoas().add(p5);
     
    Carro c3 = new Carro();
    c3.setId(3L);
    c3.setNome("Onix");        
    c3.getPessoas().add(p6);
    
    
    Carro c4 = new Carro();
    c4.setId(4L);
    c4.setNome("Corolla");        
    c4.getPessoas().add(p7);
    c4.getPessoas().add(p8);
    c4.getPessoas().add(p9);
    c4.getPessoas().add(p10);
    
    Carro c5 = new Carro();
    c5.setId(5L);
    c5.setNome("Siena");        
    c5.getPessoas().add(p11);
    c5.getPessoas().add(p12);

    Fabrica f1 = new Fabrica();
    f1.setId(1L);
    f1.setNome("Ford");
    
    Fabrica f2 = new Fabrica();
    f2.setId(2L);
    f2.setNome("Fiat");
    f2.getCarros().add(c5);
    f2.getCarros().add(c2);
            
    Fabrica f3 = new Fabrica();
    f3.setId(3L);
    f3.setNome("Toyota");
    f3.getCarros().add(c4);
    
    Fabrica f4 = new Fabrica();
    f4.setId(4L);
    f4.setNome("Chevrolet");
    f4.getCarros().add(c3);
    
    List<Fabrica> fabricas = new ArrayList<Fabrica>();
    fabricas.add(f1);
    fabricas.add(f2);
    fabricas.add(f3);
    fabricas.add(f4);

    Tela tela = new Tela(new FabricaTreeModel(fabricas));  
    tela.setVisible(true);  
}  

}
[/code]

FabricaTreeModel.java

[code]/*

  • To change this license header, choose License Headers in Project Properties.
  • To change this template file, choose Tools | Templates
  • and open the template in the editor.
    */
    package treemodelexample;

import java.util.ArrayList;
import java.util.List;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import treemodelexample.bean.Carro;
import treemodelexample.bean.Fabrica;
import treemodelexample.bean.Pessoa;

public class FabricaTreeModel 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 = "Fabricas";

// 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<Fabrica> fabricas;

public FabricaTreeModel(List<Fabrica> fabricas) {
    this.fabricas = fabricas;
}

/**
 * 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 fabricas.get(index); // Pegamos da lista de livro  
    }
    if (parent instanceof Fabrica) // O pai é um livro?  
    {
        return ((Fabrica) parent).getCarros().get(index);
    } else if (parent instanceof Carro) {
        return ((Carro) parent).getPessoas().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 fabricas.size();
    }
    if (parent instanceof Fabrica) // O pai é um livro?  
    {
        return ((Fabrica) parent).getCarros().size();
    } else if (parent instanceof Carro) {
        return ((Carro) parent).getPessoas().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 fabricas.indexOf(child);
    }
    if (parent instanceof Fabrica) {
        return ((Fabrica) parent).getCarros().indexOf(child);
    } else if (parent instanceof Carro) {
        return ((Carro) parent).getPessoas().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 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.
 */
@Override
public boolean isLeaf(Object node) {
    return node instanceof Pessoa;
}

@Override
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  
@Override
public void removeTreeModelListener(TreeModelListener l) {
    listeners.remove(l);
}

@Override
public void addTreeModelListener(TreeModelListener l) {
    listeners.add(l);
}

}
[/code]
CheckRenderer .java

[code]package treemodelexample;

import java.awt.;
import javax.swing.
;
import javax.swing.tree.*;
import javax.swing.plaf.ColorUIResource;
import treemodelexample.bean.Carro;
import treemodelexample.bean.Fabrica;
import treemodelexample.bean.Pessoa;

public class CheckRenderer extends JPanel implements TreeCellRenderer {

protected JCheckBox check;
protected TreeLabel label;

public CheckRenderer() {
    setLayout(null);
    add(check = new JCheckBox());
    add(label = new TreeLabel());
    check.setBackground(UIManager.getColor("Tree.textBackground"));
    label.setForeground(UIManager.getColor("Tree.textForeground"));
}

@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
    String stringValue = tree.convertValueToText(value, isSelected, expanded, leaf, row, hasFocus);
    setEnabled(tree.isEnabled());
    if(value instanceof Fabrica){
        check.setSelected(((Fabrica) value).isSelected());        
    }else if(value instanceof Carro){
        check.setSelected(((Carro) value).isSelected());        
    }else if(value instanceof Pessoa){
        check.setSelected(((Pessoa) value).isSelected());  
    }
    label.setFont(tree.getFont());
    label.setText(stringValue);
    label.setSelected(isSelected);
    label.setFocus(hasFocus);
    if (leaf) {
        label.setIcon(UIManager.getIcon("Tree.leafIcon"));
    } else if (expanded) {
        label.setIcon(UIManager.getIcon("Tree.openIcon"));
    } else {
        label.setIcon(UIManager.getIcon("Tree.closedIcon"));
    }
    return this;
}

@Override
public Dimension getPreferredSize() {
    Dimension d_check = check.getPreferredSize();
    Dimension d_label = label.getPreferredSize();
    return new Dimension(d_check.width + d_label.width, (d_check.height < d_label.height ? d_label.height : d_check.height));
}

@Override
public void doLayout() {
    Dimension d_check = check.getPreferredSize();
    Dimension d_label = label.getPreferredSize();
    int y_check = 0;
    int y_label = 0;
    if (d_check.height < d_label.height) {
        y_check = (d_label.height - d_check.height) / 2;
    } else {
        y_label = (d_check.height - d_label.height) / 2;
    }
    check.setLocation(0, y_check);
    check.setBounds(0, y_check, d_check.width, d_check.height);
    label.setLocation(d_check.width, y_label);
    label.setBounds(d_check.width, y_label, d_label.width, d_label.height);
}

@Override
public void setBackground(Color color) {
    if (color instanceof ColorUIResource) {
        color = null;
    }
    super.setBackground(color);
}

public class TreeLabel extends JLabel {

    boolean isSelected;
    boolean hasFocus;

    public TreeLabel() {
    }

    @Override
    public void setBackground(Color color) {
        if (color instanceof ColorUIResource) {
            color = null;
        }
        super.setBackground(color);
    }

    @Override
    public void paint(Graphics g) {
        String str;
        if ((str = getText()) != null) {
            if (0 < str.length()) {
                if (isSelected) {
                    g.setColor(UIManager.getColor("Tree.selectionBackground"));
                } else {
                    g.setColor(UIManager.getColor("Tree.textBackground"));
                }
                Dimension d = getPreferredSize();
                int imageOffset = 0;
                Icon currentI = getIcon();
                if (currentI != null) {
                    imageOffset = currentI.getIconWidth() + Math.max(0, getIconTextGap() - 1);
                }
                g.fillRect(imageOffset, 0, d.width - 1 - imageOffset, d.height);
                if (hasFocus) {
                    g.setColor(UIManager.getColor("Tree.selectionBorderColor"));
                    g.drawRect(imageOffset, 0, d.width - 1 - imageOffset, d.height - 1);
                }
            }
        }
        super.paint(g);
    }

    @Override
    public Dimension getPreferredSize() {
        Dimension retDimension = super.getPreferredSize();
        if (retDimension != null) {
            retDimension = new Dimension(retDimension.width + 3,
                    retDimension.height);
        }
        return retDimension;
    }

    public void setSelected(boolean isSelected) {
        this.isSelected = isSelected;
    }

    public void setFocus(boolean hasFocus) {
        this.hasFocus = hasFocus;
    }
}

}
[/code]
NodeSelectionListener .java

[code]package treemodelexample;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JTree;
import javax.swing.tree.TreePath;
import treemodelexample.bean.Carro;
import treemodelexample.bean.Fabrica;
import treemodelexample.bean.Pessoa;

/**
*

  • @author JUNIOR
    */
    public class NodeSelectionListener extends MouseAdapter {

    JTree tree;

    NodeSelectionListener(JTree tree) {
    this.tree = tree;
    }

    @Override
    public void mouseClicked(MouseEvent e) {
    int x = e.getX();
    int y = e.getY();
    int row = tree.getRowForLocation(x, y);
    TreePath path = tree.getPathForRow(row);
    if (path != null) {
    if (path.getLastPathComponent() instanceof Fabrica) {
    //Neste caso, indica que o usuário clicou sobre a classe pai Fabrica,
    //portanto todos os seus filhos serão marcado com o estado no qual o pai
    //está sendo, ou seja, receberá o mesmo status que o pai
    Fabrica node = (Fabrica) path.getLastPathComponent();
    boolean isSelected = !(node.isSelected());
    node.setSelected(isSelected);
    for (Carro carro : node.getCarros()) {
    carro.setSelected(isSelected);
    for (Pessoa pessoa : carro.getPessoas()) {
    pessoa.setSelected(isSelected);
    }
    }
    if (isSelected) {
    tree.expandPath(path);
    } else {
    tree.collapsePath(path);
    }

         } else if (path.getLastPathComponent() instanceof Carro) {
             //Neste caso, indica que o usuário clicou sobre a classe pai Carro,
             //portanto todos os seus filhos serão marcado com o estado no qual o pai
             //está sendo, ou seja, receberá o mesmo status que o pai
             Carro node = (Carro) path.getLastPathComponent();
             boolean isSelected = !(node.isSelected());
             boolean achouCarro = false;
             Fabrica fabrica = ((Fabrica) path.getParentPath().getLastPathComponent());
             node.setSelected(isSelected);
             for (Pessoa pessoa : node.getPessoas()) {
                 pessoa.setSelected(isSelected);
             }
             //Será necessário verificar se há outros filhos do respectivo
             //pai que estejam marcados, caso haja o pai não poderá ser desmarcado
             
                 for (Carro dadoCarro : fabrica.getCarros()) {
                     if (dadoCarro.isSelected()) {
                         achouCarro = true;
                         break;
                     }
                 }
                 if (achouCarro) {
                     fabrica.setSelected(true);
                 } else {
                     fabrica.setSelected(false);
                 }
             
    
             if (isSelected) {
                 tree.expandPath(path);
             } else {
                 tree.collapsePath(path);
             }
         } else if (path.getLastPathComponent() instanceof Pessoa) {
             Pessoa node = (Pessoa) path.getLastPathComponent();
             boolean isSelected = !(node.isSelected());
             boolean achouCarro = false;
             boolean achouPessoa = false;
             node.setSelected(isSelected);
             Carro carro = ((Carro) path.getParentPath().getLastPathComponent());
             Fabrica fabrica = ((Fabrica) path.getParentPath().getParentPath().getLastPathComponent());
             
             //Será necessário verificar se há outros filhos (Pessoas) do respectivo
             //pai que estejam marcados, caso haja o pai não poderá ser desmarcado
    
             for (Pessoa dadoPessoa : carro.getPessoas()) {
                 if (dadoPessoa.isSelected()) {
                     achouPessoa = true;
                     break;
    
                 }
             }
             if (achouPessoa) {
                 carro.setSelected(true);
             } else {
                 carro.setSelected(false);
             }
             
             //Será necessário verificar se há outros filhos (Pessoas) do respectivo
             //pai que estejam marcados, caso haja o pai não poderá ser desmarcado
             
             for (Carro dadoCarro : fabrica.getCarros()) {
                 if (dadoCarro.isSelected()) {
                     achouCarro = true;
                     break;
                 }
             }
             if (achouCarro) {
                 fabrica.setSelected(true);
             } else {
                 fabrica.setSelected(false);
             }
    
         }
         tree.setModel((FabricaTreeModel) tree.getModel());
         tree.revalidate();
         tree.repaint();
     }
    

    }
    }[/code]