Depois de muitas pesquisas no fórum e na Internet, resolver criar esse topico.
Estou criando uma pequena aplicação Swing no NetBeans que carrega uma JTable com dados de uma tabela do BD. Minha primeira dúvida é a seguinte:
1 - Criei os componentes visuais todos pelo NetBeans. A IDE gera um bando de códigos que nao podemos mexer. Eu coloquei uma JTable no meu JFrame, mas tenho dúvidas sobre como instanciar e usar esse objeto. Aparentemente, ele apenas declara uma referencia de instancia, mas não instancia. Porem, o objeto “físico” ja está no JFrame. Preciso instanciar isso na mão? " JTable jTable1 = new JTable();" ? Se sim, faço isso no construtor do JFrame?
2 - A tela ja está toda montadinha. Porem, quando estudei um pouco sobre Swing, eu lembro de ter visto que é necessário colocarmos containers e adicionarmos os componentes dentro desses containers e tal. Preciso fazer isso com a tabela? algo do tipo jFrame1.add(jTable1)? Lembrando que a tela já está toda montadinha visualmente.
3 - Não estou conseguindo popular essa JTable. Não sei se é por causa dos problemas acima ou se nao estou conseguindo realmente trazer os dados do banco. Tenho uma LIST com todos os dados da tabela. Queria apenas jogar essa LIST pra dentro da JTable. Existe alguma forma de jogar um ResultSet? acho que seria mais fácil.
Me surpreendeu ninguem ter respondido até o momento. Vou dar um exemplo abaixo, talvez haja métodos mais fáceis, mas se persistir há de conseguir. Aqui funciona redondinho.
Coloque a jTable na mão mesmo pelo NB.
Crie uma classe que extenda DefaultTableModel e atribua na sua jTable da seguinte forma:
Note que estou levando os dados do DB num ArrayList
...
ModelTableRDV model = null;
model = new ModelTableRDV(al); // aqui passo o arraylista para a classe que extenda a DefaultTableModel
jTableRDV.setModel(model);
jTableRDV.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
}
Abaixo postarei a classe ModelTableRDV descrita acima:
package util;
import javax.swing.table.DefaultTableModel;
import bean.RDV;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
public class ModelTableRDV extends DefaultTableModel {
private ArrayList dados = null;
public ModelTableRDV(ArrayList dados) {
this.dados = dados;
}
@Override
public int getColumnCount() {
return 6; //quantidade de campos do que terá na tabela
}
@Override
public int getRowCount() {
if (this.dados == null) {
return 0;
} else {
return this.dados.size();
}
}
@Override
public Object getValueAt(int row, int column) {
RDV rdv = (RDV) this.dados.get(row); // RDV é o meu objeto bean com seus gets e sets
Object retorno = null;
if (column == 0) { //pega os valores do objeto para retornar para a jTable
retorno = rdv.getDespVeicNum();
} else if (column == 1) {
retorno = rdv.getDespVeicData();
} else if (column == 2) {
retorno = rdv.getDespVeicOrigem();
} else if (column == 3) {
retorno = rdv.getDespVeicDestino();
} else if (column == 4) {
retorno = rdv.getDespVeicKmTot();
} else if (column == 5) {
retorno = rdv.getDespVeicVlrTotal();
}
return retorno;
}
@Override
public String getColumnName(int column) {
String columnName = ""; //rotulo de cabeçalho das colunas do jTable
if (column == 0) {
columnName = "ID:";
} else if (column == 1) {
columnName = "Data:";
} else if (column == 2) {
columnName = "Origem:";
} else if (column == 3) {
columnName = "Destino:";
} else if (column == 4) {
columnName = "KM Total:";
} else if (column == 5) {
columnName = "Valor Total:";
}
return columnName;
}
}
Deve funcionar, testa aí e retorne se precisar. Caso haja algum amigo que saiba uma maneira mais fácil de fazer, poste por favor.
A diferença é que o DefaultTableModel é uma classe concreta, subclasse de AbstractTableModel, que é instanciada e setada automaticamente em uma JTable, caso tu não substitua ele definindo um novo setModel. Portanto, uma classe que já existem muitos métodos para manipulação de dados, nesse caso do tipo arrays e vector. A idéia de um novo TableModel é modificar essa manipulação de dados. Portanto uma classe que já tem todos os métodos necessários para esse fim e uso definido: Definição e manipulação dos dados através de um vector de dados. Extendendo uma DefaultTableModel, e não uma AbstractTableModel, sua classe vai ficar inchada com métodos que nunca serão utilizadas, já que a idéia é justamente modificar o jeito de manipulação de dados. Para isso, extendendo AbstractTableModel, você herda apenas os métodos realmente necessários, e aí sim, implementa os novos métodos para manipulação de dados, sem repetição.
Estou com um segundo problema agora… To implementando o método de exclusão, onde desejo fazer o seguinte: Quando o usuario clica em um registro da JTable, gostaria que um objeto fosse retornado. Este objeto eu mandaria como parametro para meu DAO de exclusão.
Mas percebi que os métodos que tenho disponíveis não fazem isso. Para pegar um valor, eu preciso dar um getValueAt(int row, int column) mandando o numero da linha e da coluna. Mas eu não sei em tempo de execução qual será a coluna que o usuario irá clicar. Eu preciso de um método que pegue a linha inteira e monte um objeto com esses valores. Esse método exsite?
Alterei o modelo da minha tabela, colocando o método getColumnClass() e mudando o getValueAt() para setar na primeira coluna um JCheckBox (que foi inserido no bean do objeto). Dessa forma deu erro, pois não foi possível dar o cast em um objeto JCheckBox para um Boolean.
Alterei o retorno da primeira coluna do metodo getColumnClass() para JCheckBox.class. Dessa forma não tem erro, mas ao invés de aparecer um checkbox, aparece apenas o nome do objeto.
O que eu gostaria de fazer é colocar os checkbox, para que possa validar/assinar/enviar várias notas fiscais de uma só vez. Qual a melhor forma para isso?
public class ModelTabelaDados extends AbstractTableModel {
/**
*
*/
private static final long serialVersionUID = 1L;
private ArrayList<NotaFiscal> dados = null;
public ModelTabelaDados(ArrayList<NotaFiscal> dados) {
this.dados = dados;
}
@Override
public int getColumnCount() {
return 7; //quantidade de campos do que terá na tabela
}
@Override
public int getRowCount() {
if (this.dados == null) {
return 0;
} else {
return this.dados.size();
}
}
@Override
public Object getValueAt(int row, int column) {
NotaFiscal notaFiscal = (NotaFiscal) this.dados.get(row); // RDV é o meu objeto bean com seus gets e sets
Object retorno = null;
if (column == 0) { //pega os valores do objeto para retornar para a jTable
retorno = notaFiscal.getCheckBox();
} else if (column == 1) {
retorno = notaFiscal.getNumero();
} else if (column == 2) {
retorno = notaFiscal.getEmpresa();
} else if (column == 3) {
retorno = notaFiscal.getCliente();
} else if (column == 4) {
retorno = notaFiscal.getValor();
} else if (column == 5) {
retorno = notaFiscal.getData();
} else if (column == 6) {
retorno = notaFiscal.getSituacaoDecodificada();
}
return retorno;
}
@Override
public String getColumnName(int column) {
String columnName = ""; //rotulo de cabeçalho das colunas do jTable
if (column == 0) {
columnName = "";
} else if (column == 1) {
columnName = "NUMERO";
} else if (column == 2) {
columnName = "EMPRESA";
} else if (column == 3) {
columnName = "CLIENTE";
} else if (column == 4) {
columnName = "VALOR";
} else if (column == 5) {
columnName = "DATA";
} else if (column == 6) {
columnName = "SITUACAO";
}
return columnName;
}
@Override
public Class getColumnClass(int column){
if (column == 0) {
return Boolean.class;
} else if (column == 1) {
return String.class;
} else if (column == 2) {
return String.class;
} else if (column == 3) {
return String.class;
} else if (column == 4) {
return String.class;
} else if (column == 5) {
return String.class;
} else if (column == 6) {
return String.class;
} else {
return String.class;
}
}
}
Você não deve retornar um checkbox no getValueAt. Basta retornar o valor boolean que está definido na coluna (true ou false). O JTable se encarrega de renderizar esse boolean como um checkbox.