MyAbstractTableModelDinamicForever

Quando precisamos utilizar JTables, somos obrigado a fornecer um modelo de dados para ela. Isso se dá usando a classe DefaultTableModel ou criando uma subclasse de AbstractTableModel.

O problemas é que muitas vezes, queremos apenas mostrar alguns dados e poder alterá-los.

Utilizando DefaultTableModel temos que fornecer um vetor de dados e outro de colunas. Com os dados no vetor, a manipulação fica meio complicado por diversos fatores como aumentar sua capacidade.

Outra possibilidade é fornecer um Vector com os dados e outro com as colunas. O Vector é uma classe sincronizada, o que significa perda de performance sendo que muitas vezes não precisaremos de uma estrutura de dados sincronizada.

Criando nossa própria subclasse de AbstractTableModel pode ser um pouco trabalhoso pois poderemos ter diversos TableModels para apenas mostrar dados.

A solução que encontrei foi implementar a classe AbstractTableModel para que receba uma List generica e através de Reflection, acesse os campos tanto para mostrar nas células quanto para atualização.

Para criar a classe de Reflection utilizei o pacote org.apache.commons.beanutils que pode ser baixado em http://commons.apache.org/beanutils/download_beanutils.cgi

Utilizando a classe PropertyUtils, temos os métodos setSimpleValue(target, fieldName, data) que atualiza uma propriedade e o método getSimpleValue(target, fieldName), para acessar uma propriedade, desde que a mesma esteja encapsulada (get() set()).

Então, a classe TableModelDinamic ficará assim:

import java.util.List;
import javax.swing.table.AbstractTableModel;
import orquestralibrary.util.Reflection;

public class TableModelDinamic extends AbstractTableModel {

    protected List list;

    protected String[] columnNames;

    public TableModelDinamic() {
        super();
    }

    public TableModelDinamic(List list) {
        setList(list);
    }

    public TableModelDinamic(List list, String [] cols)
    {
        setList(list);
        columnNames = cols;
    }
   
    public int getRowCount() {
        return list.size();
    }

    public int getColumnCount() {

        if(columnNames == null)
            return list.get(0).getClass()
                    .getDeclaredFields().length;

        return columnNames.length;
    }

    public Object getValueAt(int row, int column) {

        return Reflection.getFieldValue(list.get(row), getFieldName(column));
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        Reflection.setFieldValue(list.get(rowIndex), getFieldName(columnIndex), aValue);
    }
    private String getFieldName(int idx)
    {
        if(columnNames == null)
            return list.get(0).getClass()
                    .getDeclaredFields()[idx].getName();

        return columnNames[idx];
    }

    @Override
    public String getColumnName(int column) {
        return getFieldName(column);
    }

    public List getList() {
        return list;
    }

    public void setList(List _list) {
        list = _list;
        fireTableDataChanged();
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return true;
    }
}

O construtor do nosso model recebe uma lista como argumento no construtor ou uma lista mais os nomes das colunas que serão mostradas na JTable.

Se voce quiser trocar a lista, basta usar o método setList do model.

Para utilizar esta classe, basta apenas instanciar o model passando a sua lista.

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

/**
 *
 * @author marciliosouza
 */
public class Frame extends javax.swing.JFrame {

    /** Creates new form Frame */
    public Frame() {
        super("Simple TableModel");
        initComponents();
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        jButton1 = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();
        jButton2 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jButton1.setText("Proximo");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        jTable1.setModel(getModel());
        jScrollPane1.setViewportView(jTable1);

        jButton2.setText("Imprimir");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 375, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jButton2)
                        .addGap(77, 77, 77)
                        .addComponent(jButton1)))
                .addGap(21, 21, 21))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 275, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton1)
                    .addComponent(jButton2))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {

        ((TableModelDinamic)jTable1.getModel()).setList(getNextList());
    }

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {

        for(Object p : ((TableModelDinamic)jTable1.getModel())
                .getList())
        {
            System.out.println("Nome .: "+((Pessoa)p).getNome() +" Profissao .: "+ ((Pessoa)p).getProfissao() + " Idade .: "+((Pessoa)p).getIdade());
        }
        System.out.println();
    }

    List<List<Pessoa>> lists;
    int idx = 0;
    public List<Pessoa> getNextList()
    {

        if(lists == null)
        {
            List<Pessoa> list1 = new ArrayList<Pessoa>();

            list1.add(new Pessoa("Jose", 33, "Arquiteto"));
            list1.add(new Pessoa("Maria", 29, "Medica"));

            List<Pessoa> list2 = new ArrayList<Pessoa>();

            list2.add(new Pessoa("Marcilio", 22, "Programdor"));
            list2.add(new Pessoa("Kelly", 22, "Psicologa"));

            List<Pessoa> list3 = new ArrayList<Pessoa>();

            list3.add(new Pessoa("Alexandre", 24, "Programdor"));
            list3.add(new Pessoa("Natalia", 22, "Empresaria"));

            List<Pessoa> list4 = new ArrayList<Pessoa>();

            list4.add(new Pessoa("Jalim", 24, ""));

            lists = new ArrayList<List<Pessoa>>();
            lists.add(list1);
            lists.add(list2);
            lists.add(list3);
            lists.add(list4);
        }

        if(idx <= lists.size()-1)
            return lists.get(idx++);

        idx = 0;
        return lists.get(idx);

    }
    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        new Frame().setVisible(true);
    }

    // Variables declaration - do not modify
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable jTable1;
    // End of variables declaration

    public TableModelDinamic getModel()
    {
        return new TableModelDinamic(getNextList());
    }
}

Em alguns casos, mesmo utilizando nosso TableModelDinamic, pode ser preciso criar um model especifico. Um exemplo disso é prcisarmos informar em uma coluna uma “quantidade”, em outra o “preco” e queremos que em uma terceira coluna, seja mostrado um subtotal.

Neste caso podemos estender TableModelDinamic e fazer estes cálculos no método setValue.

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Sair / Alterar )

Imagem do Twitter

You are commenting using your Twitter account. Sair / Alterar )

Foto do Facebook

You are commenting using your Facebook account. Sair / Alterar )

Connecting to %s


Seguir

Obtenha todo post novo entregue na sua caixa de entrada.