Desculpa tanta demora para continuar o material, mas aqui estou.
Dando continuidade aos posts anteriores, vamos aprender como implementar edição em células do JTable.
Desta forma, podemos modificar nossos registros diretamente no table.
Inicialmente, vamos acrescentar dois novos métodos em nossa classe FuncionarioTableModel.
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
Funcionario f = listaFuncionario.get(rowIndex);
switch (columnIndex) {
case 0:
f.setNome(aValue.toString());
break;
case 1:
f.setIdade(Integer.parseInt(aValue.toString()));
break;
case 2:
f.setDepartamento(aValue.toString());
break;
case 3:
f.setCargo(aValue.toString());
break;
}
fireTableCellUpdated(rowIndex, columnIndex);
}
O método isCellEditable determina quais células serão editadas na table. Neste exemplo todas as células serão editáveis. Mas, vamos imaginar que gostaríamos de editar somente a primeira coluna. Dessa forma iremos ter algo semelhante a isto:
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 0;
}
Tudo depende de sua necessidade.
Sabendo que a table somente cuida da parte visual, temos de setar os valores editados em nosso objeto Funcionario após a edição. Isso trás a necessidade da implementação do método setValueAt. Não há mistério com o entendimento deste método, basta ter em mente que cada linha corresponde a um index da List e que cada coluna representa um atributo do objeto contido na List. E não se esqueça do disparo fireTableCellUpdated para garantir a renderização da célula editada.
Pronto!
Agora você já tem um JTable com as células editáveis. Fácil né?!
O que há de mais legal nisso é que a validação do valor já é feito de forma automática. Tente editar a idade colocando um valor diferente de Integer. Além de não permitir ainda destaca de vermelho! Isto acontece porque no nosso TableModel determinamos que a coluna idade seria do tipo Integer no método getColumnClass.
Mas não seria melhor se a idade fosse editada em um JSpinner e o departamento e o cargo em um JComboBox?
Assim sendo, lhes apresento a classe DefaultCellEditor.
Acrescente as seguintes linhas na classe TableModelTeste:
this.tableFuncionario.getColumn("Cargo").setCellEditor(
new DefaultCellEditor(new JComboBox(
new String[]{"Desenvolvedor", "Estagiario", "Gerente de Projetos", "Auxiliar Administrativo", "Contador", "Supervisor"})));
this.tableFuncionario.getColumn("Departamento").setCellEditor(
new DefaultCellEditor(new JComboBox(
new String[]{"Centro Tecnologico", "Recepcao", "Administracao", "RH"})));
A classe DefaultCellEditor já tem em seu construtor três possíveis componentes para edição: JTextField, JCheckBox e JComboBox. Basta adiciona-los sem mais delongas que todo o "trabalho sujo" será feito. Agora vamos fazer nosso próprio CellEditor com o JSpinner.
import java.awt.Component;
import javax.swing.AbstractCellEditor;
import javax.swing.JSpinner;
import javax.swing.JTable;
import javax.swing.SpinnerNumberModel;
import javax.swing.table.TableCellEditor;
public class IdadeCellEditor extends AbstractCellEditor implements TableCellEditor{
private JSpinner spinner;
private Funcionario funcionario;
public IdadeCellEditor() {
}
@Override
public Object getCellEditorValue() {
return spinner.getValue();
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
spinner = new JSpinner(new SpinnerNumberModel(0, 0, null, 1));
spinner.setValue(value);
funcionario = ((FuncionarioTableModel)table.getModel()).getFuncionario(row);
return spinner;
}
@Override
public boolean stopCellEditing() {
funcionario.setIdade(Integer.parseInt(spinner.getValue().toString()));
return super.stopCellEditing();
}
}
Com isto podemos editar a célula usando o JSpinner.
O método getCellEditorValue retorna o novo valor após a edição para renderização. No método getTableCellEditorComponent definimos qual o componente vai ser apresentado para edição, no nosso caso, o JSpinner. O spinner é iniciado com o valor da célula e temos que recuperar também o funcionário para que possamos em seguida atualizar o objeto da lista. No método stopCellEditing setamos o novo valor para o funcionário em questão.
Para utilizar o nosso CellEditor criado, acrescentamos na classe TableModelTeste:
this.tableFuncionario.setDefaultEditor(Integer.class, new IdadeCellEditor());
Com isto, agora podemos editar a idade com o spinner.
Concluímos aqui este material. Ainda existe uma série de coisas que podemos fazer com o JTable. Ainda podemos brincar com a renderização do objeto. Por exemplo, podemos colocar imagens nas células.
Caso tenham curiosidade de como fazer isso, só deixar comentário.
Espero que isso seja de grande ajuda e até a próxima.