Criando seu modelo de tabela [AbstractTableModel]

Olá pessoal. 😀

Desculpem á ausência, faculdade está á todo vapor, rsrsrs…

Brincadeiras a parte vamos para um excelente tutorial, neste tutorial vamos aprender a criar um modelo de tabela para JTable.

Este modelo contará com métodos para sua persistência poderemos por exemplo inserir e remover linhas.

Crie um projeto no eclipse IDE , com nome SampleTableModel.

Após criar o projeto, crie a 1° classe com nome Empregado no pacote br.modelo, será o objeto Java Bean do projeto, abaixo o código completo.

package br.modelo;

import java.sql.Date;

/**
 * classe Javabean entidade Empregado
 * @author Roberto Silva
 */
public class Empregado {
	private String  nome;
	private int     idade;
	private char    sexo;
	private Date    dataNasc;
	private double  salario;
	private boolean beneficio;

	public Empregado() {
		//inicializando variaveis
		this.nome="";
		this.idade=0;
		this.sexo='M';
		this.dataNasc=new Date(new java.util.Date().getTime());
		this.salario=0;
		this.beneficio=true;
	}

	/**
	 * @return the nome
	 */
	public String getNome() {
		return nome;
	}

	/**
	 * @param nome the nome to set
	 */
	public void setNome(String nome) {
		this.nome = nome;
	}

	/**
	 * @return the idade
	 */
	public int getIdade() {
		return idade;
	}

	/**
	 * @param idade the idade to set
	 */
	public void setIdade(int idade) {
		this.idade = idade;
	}

	/**
	 * @return the sexo
	 */
	public char getSexo() {
		return sexo;
	}

	/**
	 * @param sexo the sexo to set
	 */
	public void setSexo(char sexo) {
		this.sexo = sexo;
	}

	/**
	 * @return the dataNasc
	 */
	public Date getDataNasc() {
		return dataNasc;
	}

	/**
	 * @param dataNasc the dataNasc to set
	 */
	public void setDataNasc(Date dataNasc) {
		this.dataNasc = dataNasc;
	}

	/**
	 * @return the salario
	 */
	public double getSalario() {
		return salario;
	}

	/**
	 * @param salario the salario to set
	 */
	public void setSalario(double salario) {
		this.salario = salario;
	}

	/**
	 * @return the beneficio
	 */
	public boolean isBeneficio() {
		return beneficio;
	}

	/**
	 * @param beneficio the beneficio to set
	 */
	public void setBeneficio(boolean beneficio) {
		this.beneficio = beneficio;
	}

}

Agora neste ponto vamos criar á nossa “Table Model” é uma classe que estende AbstractTableModel,

esta classe possui métodos de herança, após estender terá que sobreescrever alguns métodos.

Crie a 2° classe com nome EmpregadoTableModel no pacote br.modelo, abaixo o código completo.

package br.modelo;

import java.sql.Date;
import java.util.List;
import javax.swing.table.AbstractTableModel;

/**
 * classe Table Model "modelo de tabela" p/entidade Empregado
 * @author Roberto Silva
 */
public class EmpregadoTableModel extends AbstractTableModel{

	//constantes p/identificar colunas
	private final int NOME=0;
	private final int IDADE=1;
	private final int SEXO=2;
	private final int DATA_NASC=3;
	private final int SALARIO=4;
	private final int BENEFICIO=5;

	private final String colunas[]={"Nome:","Idade:","Sexo:","Data.Nasc:","Salário:","Beneficio:"};
	private final List<Empregado> dados;//usamos como dados uma lista genérica de Empregado

	public EmpregadoTableModel(List<Empregado> dados) {
		//seto os dados no construtor
		this.dados=dados;
	}

	@Override
	public int getColumnCount() {
		//retorna o total de colunas
		return colunas.length;
	}

	@Override
	public int getRowCount() {
		//retorna o total de linhas na tabela
		return dados.size();
	}

	@Override
	public Class<?> getColumnClass(int columnIndex) {
		//retorna o tipo de dado, para cada coluna
		switch (columnIndex) {
		case NOME:
			return String.class;
		case IDADE:
			return int.class;
		case SEXO:
			return char.class;
		case DATA_NASC:
			return Date.class;
		case SALARIO:
			return double.class;
		case BENEFICIO:
			return Boolean.class;
		default:
			throw new IndexOutOfBoundsException("Coluna Inválida!!!");
		}
	}

	@Override
	public String getColumnName(int columnIndex) {
		return colunas[columnIndex];
	}

	@Override
	public Object getValueAt(int rowIndex, int columnIndex) {
		//retorna o valor conforme a coluna e linha

		//pega o dados corrente da linha
		Empregado empregado=dados.get(rowIndex);

		//retorna o valor da coluna
		switch (columnIndex) {
		case NOME:
			return empregado.getNome();
		case IDADE:
			return empregado.getIdade();
		case SEXO:
			return empregado.getSexo();
		case DATA_NASC:
			return empregado.getDataNasc();
		case SALARIO:
			return empregado.getSalario();
		case BENEFICIO:
			return empregado.isBeneficio();
		default:
			throw new IndexOutOfBoundsException("Coluna Inválida!!!");
		}
	}

	@Override
	public boolean isCellEditable(int rowIndex, int columnIndex) {
		//metodo identifica qual coluna é editavel

		//só iremos editar a coluna BENEFICIO, 
		//que será um checkbox por ser boolean
		if(columnIndex == BENEFICIO)
			return true;

		return false;
	}

	@Override
	public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
		Empregado empregado=dados.get(rowIndex);

		if(columnIndex == BENEFICIO){
			empregado.setBeneficio(((boolean)aValue));
		}
	}

	//Métodos abaixo são para manipulação de dados

	/**
	 * retorna o valor da linha indicada
	 * @param rowIndex
	 * @return
	 */
	public Empregado getValue(int rowIndex){
		return dados.get(rowIndex);
	}

	/**
	 * retorna o indice do objeto
	 * @param empregado
	 * @return
	 */
	public int indexOf(Empregado empregado) {
		return dados.indexOf(empregado);
	}

	/**
	 * add um empregado á lista
	 * @param empregado
	 */
	public void onAdd(Empregado empregado) {
		dados.add(empregado);
		fireTableRowsInserted(indexOf(empregado), indexOf(empregado));
	}

	/**
	 * add uma lista de empregados
	 * @param dadosIn
	 */
	public void onAddAll(List<Empregado> dadosIn) {
		dados.addAll(dadosIn);
		fireTableDataChanged();
	}

	/**
	 * remove um registro da lista, através do indice
	 * @param rowIndex
	 */
	public void onRemove(int rowIndex) {
		dados.remove(rowIndex);
		fireTableRowsDeleted(rowIndex, rowIndex);
	}

	/**
	 * remove um registro da lista, através do objeto
	 * @param empregado
	 */
	public void onRemove(Empregado empregado) {
        int indexBefore=indexOf(empregado);//pega o indice antes de apagar
        dados.remove(empregado);  
		fireTableRowsDeleted(indexBefore, indexBefore);
	}

	/**
	 * remove todos registros da lista
	 */
	public void onRemoveAll() {
		dados.clear();
		fireTableDataChanged();
	}

}

Crie a 3° classe com nome GUIPrincipal no pacote br.visual, será a classe visual,
irá fazer a interface com usuário, abaixo o código completo.

package br.visual;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;

import br.modelo.Empregado;
import br.modelo.EmpregadoTableModel;

/**
 * classe JFrame "Formulário Java", U.I-User Interface
 * @author Roberto Silva
 */
public class GUIPrincipal extends JFrame{

	private JTable table=new JTable();
	private EmpregadoTableModel tableModel;

	private JButton btnAdd=new JButton("Adicionar Linha");
	private JButton btnRem=new JButton("Remover Linha");
	private JButton btnAddAll=new JButton("Adicionar Dados");
	private JButton btnRemAll=new JButton("Remover Dados");;

	public GUIPrincipal() {
		//setando respectivamente...
		//titulo
		this.setTitle("Exemplo de Table Model");
		//layout
		this.setLayout(new FlowLayout());
		//tamanho do JFrame
		this.setSize(new Dimension(600, 400));
		//tipo de fechamento da janela
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//centralizando a janela
		this.setLocationRelativeTo(null);

		//neste ponto é criado o modelo da JTable
		tableModel=new EmpregadoTableModel(getListaEmpregados());

		//setando propriedades da tabela...

		//modelo
		table.setModel(tableModel);
		//barra de rolagem
        table.setPreferredScrollableViewportSize(new Dimension(500,300));
        //auto ajuste na altura da tabela
        table.setFillsViewportHeight(true);
        //selecionar somente uma linha
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        //add a table ao scroll pane
		JScrollPane scrollPane=new JScrollPane(table);
		this.add(scrollPane);

		//add eventos aos botões
		btnAdd.addActionListener(btnAddListener);
		btnRem.addActionListener(btnRemListener);
		btnAddAll.addActionListener(btnAddAllListener);
		btnRemAll.addActionListener(btnRemAllListener);

		//add botões ao JFrame
		this.add(btnAdd);
		this.add(btnRem);
		this.add(btnAddAll);
		this.add(btnRemAll);
	}

	/**
	 * retorna uma lista de empregados
	 * @return {@link List} {@link Empregado}
	 */
	private List<Empregado> getListaEmpregados(){
		//criado lista e seu conteudo os empregados
		//setando suas propriedades
		List<Empregado> empregados=new ArrayList<Empregado>();

		Empregado emp1=new Empregado();
		emp1.setNome("Jack");
		emp1.setIdade(19);
		emp1.setSexo('M');
		emp1.setSalario(2500);

		Empregado emp2=new Empregado();
		emp2.setNome("Eddie");
		emp2.setIdade(56);
		emp2.setSexo('M');
		emp2.setSalario(7500);

		Empregado emp3=new Empregado();
		emp3.setNome("Gina");
		emp3.setIdade(34);
		emp3.setSexo('F');
		emp3.setSalario(5500);

		Empregado emp4=new Empregado();
		emp4.setNome("Klaus");
		emp4.setIdade(18);
		emp4.setSexo('M');
		emp4.setSalario(1500);

		Empregado emp5=new Empregado();
		emp5.setNome("Erick");
		emp5.setIdade(20);
		emp5.setSexo('F');
		emp5.setSalario(1600);

		Empregado emp6=new Empregado();
		emp6.setNome("Robert");
		emp6.setIdade(30);
		emp6.setSexo('M');
		emp6.setSalario(4500);

		Empregado emp7=new Empregado();
		emp7.setNome("Mary");
		emp7.setIdade(30);
		emp7.setSexo('F');
		emp7.setSalario(4500);

		//add á lista os empregados criados
		empregados.add(emp1);
		empregados.add(emp2);
		empregados.add(emp3);
		empregados.add(emp4);
		empregados.add(emp5);
		empregados.add(emp6);
		empregados.add(emp7);

		return empregados;
	}

	/*
	 * Eventos do botões, poderia ser criado classes que fossem "extends ActionListener"
	 * mas como se trata de um exemplo, vamos simplificar 😉
	 * */

	//evento p/adicionar um registro á tabela
	private ActionListener btnAddListener=new ActionListener() {
		@Override
		public void actionPerformed(ActionEvent e) {
			//sorteia um indice do tamanho da lista para baixo
			//exemplo se a lista tiver o tamanho 10 , então vai de 0 até 9
			int randomIndex=(int)(Math.random()* (tableModel.getRowCount()-1));
			Empregado empregado=tableModel.getValue(randomIndex);
			tableModel.onAdd(empregado);
		}
	};

	//evento p/remover um registro da tabela
	private ActionListener btnRemListener=new ActionListener() {
		@Override
		public void actionPerformed(ActionEvent e) {
			if(table.getSelectedRow() != -1 && table.getSelectedRow() < tableModel.getRowCount()){
				tableModel.onRemove(table.getSelectedRow());
			}else
				JOptionPane.showMessageDialog(null, "Selecione um registro da tabela!");
		}
	};

	//evento p/adicionar um vários registros á tabela
	private ActionListener btnAddAllListener=new ActionListener() {
		@Override
		public void actionPerformed(ActionEvent e) {
			tableModel.onAddAll(getListaEmpregados());
		}
	};

	//evento p/remover vários registros á tabela
	private ActionListener btnRemAllListener=new ActionListener() {
		@Override
		public void actionPerformed(ActionEvent e) {
			tableModel.onRemoveAll();
		}
	};
}

Crie a 4° e última classe com nome Main no pacote br.visual, será a classe principal do projeto, onde tem o método main(…),abaixo o código completo.

package br.visual;

/**
 * classe Principal, onde é executado o sistema
 * @author Roberto Silva
 */
public class Main {
	public static void main(String[] args) {
		//instanciou
		GUIPrincipal principal=new GUIPrincipal();
		//tornou visivel
		principal.setVisible(true);
	}
}

Após o termino execute a classe Main do projeto, teremos este resultado…

JTable com model do tipo AbstractTableModel

Polpei comentários no post,  pois o código está bem comentado, em breve adiciono comentários se necessário.

Fique a vontade para deixar seu comentário em caso de dúvida, sugestão ou crítica.

Download do projeto neste link.

Exemplo modificado com eventos separados em classes Listeners neste link

Obrigado pela visita e até o próximo post. 😉