Pessoal como eu verifico se minha linha esta preenchida no JTable.? Por exemplo se minha primeira linha estiver preenchida eu adiciono os dados na segunda e assim por diante. No meu TableModel eu passo um List no construtor e uso essa lista no metodo getValueAt, e então ele sobreescreve a primeira linha em vez de ir adicionando dinamicamente.
Verificar linha preenchida no JTable
23 Respostas
Crie um método add(User user) e nesse método, faça um add na sua lista.
Vini, desculpa ignorancia mas nao entendi bem, esse método add vou criar onde no model? E esse add vou passar um objeto usuario daí como vou setar eles la linha do JTable sem o getValueAt?
No model. Dentro do seu model existe um List<User> certo?
Então vc faz assim:
public void add(User usuario) {
lista.add(usuario);
fireTableRowsInserted(lista.size()-1, lista.size()-1);
}
Isso vai adicionar o usuário ao final da sua lista, e avisar o JTable que tem linha nova para ele pintar.
No model. Dentro do seu model existe um List<User> certo?Então vc faz assim:
public void add(User usuario) { lista.add(usuario); fireTableRowsInserted(lista.size()-1, lista.size()-1); }Isso vai adicionar o usuário ao final da sua lista, e avisar o JTable que tem linha nova para ele pintar.
sim mas como vou fazer pra JTable chamar esse método? Por que o getValueAt o proprio Table o faz e este método add como faço?
no meu cod ta assim:
if(e.getSource() == this.buttonCadastrar){
if(!this.text.getText().isEmpty()){
User user = new User();
List<User> list = new ArrayList<User>();
user.setNome(this.text.getText());
user.setTel(this.textTel.getText());
list.add(user);
JOptionPane.showMessageDialog(null,"Cadastro concluido com sucesso:\n" +
this.text.getText() +" " +this.textTel.getText());
this.table.setModel(new ModelTable(list)); // AQUI CHAMO MEU MODEL....
}else{
JOptionPane.showMessageDialog(null, "Não há pessoas para cadastrar.");
}
return;
}
Ali você está criando um novo model. Você só deve criar o model uma única vez, quando criar a tela. Naquele local você deveria só fazer:
modelTable.add(user);
Note que vc também está criando uma nova lista de usuários a cada usuário inserido. E isso também não está certo.
Ali você está criando um novo model. Você só deve criar o model uma única vez, quando criar a tela. Naquele local você deveria só fazer:modelTable.add(user);Note que vc também está criando uma nova lista de usuários a cada usuário inserido. E isso também não está certo.
Veja como ta meu Model:
package com.table.models;
import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;
import com.model.User;
public class ModelTable extends AbstractTableModel{
List<User> lista;
private int COLUMN_NOME = 0;
private int COLUMN_TEL = 0;
static int contador = 0;
public ModelTable(List<User> list){
this.lista = new ArrayList<User>(list);
}
@Override
public int getColumnCount() {
// TODO Auto-generated method stub
return 2;
}
@Override
public int getRowCount() {
// TODO Auto-generated method stub
return this.lista.size();
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
User usuario = this.lista.get(rowIndex);
if(this.COLUMN_NOME == columnIndex){
return usuario.getNome(); // vai dar nullPointer aqui...
}
if(this.COLUMN_TEL == columnIndex){
return usuario.getTel();
}
return usuario.getTel();
}
public String getColumnName(int columIndex){
if(columIndex == this.COLUMN_NOME){
return "Usuário";
}
if (columIndex == this.COLUMN_TEL){
return "Telefone";
}
return "Telefone";
}
public void add(User usuario) {
lista.add(usuario);
this.fireTableRowsInserted(lista.size()-1, lista.size()-1);
}
}
Se eu criar meu model na inicializaçao do JTable vai dar nullPointer pois tenho que passar um List<User> pro construtor e no método getValueAt vai dar nullPointer.
E a ideia de um novo list seria pra armazenar um unico user pra preencher uma determinada linha...
Então, vc pode passar um List vazio, para ter um JTable vazio.
Ou você passa um List carregado do banco. Isso depende do que você quer exibir.
Mas o model vc cria uma vez só. E depois, só adiciona, retira ou modifica coisas dentro dele.
Então, vc pode passar um List vazio, para ter um JTable vazio.
Ou você passa um List carregado do banco. Isso depende do que você quer exibir.Mas o model vc cria uma vez só. E depois, só adiciona, retira ou modifica coisas dentro dele.
Entao devo modificar meu construtor e posso deixar no default? Com isso meu metodo getValueAt() nao seria mais usado correto? E adicionaria apartir do metodo add()…
Isso. Pode criar um construtor default que crie a lista em branco, eu geralmente faço isso também.
Aliás, com o seu TableModel próprio, a idéia é nunca mais usar os métodos getValueAt e setValueAt.
Deixa esses métodos para o JTable usar.
Para você crie métodos como
public User get(int row) {
lista.get(row);
}
Que te retorne um usuário inteiro. Ou método como add e remove que também aceitem como um usuário como parâmetro. E é isso que vai deixar o código da sua interface gráfica ridiculamente mais simples do que se você usasse o Default.
Isso. Pode criar um construtor default que crie a lista em branco, eu geralmente faço isso também.Aliás, com o seu TableModel próprio, a idéia é nunca mais usar os métodos getValueAt e setValueAt.
Deixa esses métodos para o JTable usar.Para você crie métodos como
public User get(int row) { lista.get(row); }Que te retorne um usuário inteiro. Ou método como add e remove que também aceitem como um usuário como parâmetro. E é isso que vai deixar o código da sua interface gráfica ridiculamente mais simples do que se você usasse o Default.
Se eu nao vou mais usar um list no construtor Vini, como vou fazer pra add nas linhas do Table? Os dois exemplos que vc me passou tanto do add quanto do get estao usando um list pra adicionar porém usando um construtor Default no meu model como vou fazer pra add agora? Sendo que JTable vai procurar getValueAt e o mesmo estara retornando null.
package com.table.models;
import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;
import com.model.User;
public class ModelTable extends AbstractTableModel{
List<User> lista = new ArrayList(); // NAO TENHO MAIS ESTA LISTA...
private int COLUMN_NOME = 0;
private int COLUMN_TEL = 0;
@Override
public int getColumnCount() {
// TODO Auto-generated method stub
return 2;
}
@Override
public int getRowCount() {
// TODO Auto-generated method stub
return 2;
}
public String getColumnName(int columIndex){
if(columIndex == this.COLUMN_NOME){
return "Usuário";
}
if (columIndex == this.COLUMN_TEL){
return "Telefone";
}
return "Telefone";
}
public void add(User usuario) {
lista.add(usuario);
this.fireTableRowsInserted(lista.size()-1, lista.size()-1);
}
@Override
public Object getValueAt(int arg0, int arg1) {
// TODO Auto-generated method stub
return null;
}
}
private JTable getTable(){
if(this.table == null){
this.table = new JTable();
this.model = new ModelTable();
table.setModel(model);
table.setVisible(true);
}
return this.table;
}
Onde chamo o add...
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == this.buttonCadastrar){
if(!this.text.getText().isEmpty()){
User user = new User();
//List<User> list = new ArrayList<User>();
user.setNome(this.text.getText());
user.setTel(this.textTel.getText());
//list.add(user);
JOptionPane.showMessageDialog(null,"Cadastro concluido com sucesso:\n" +
this.text.getText() +" " +this.textTel.getText());
this.model.add(user);
A duvida maior, é como vou adicionar os dados porque eu entendi que o proprio JTable chama o getValueAt pra adicionar os dados nas linhas, porém ele agora esta retornando null mas mesmo assim JTable o vai chamar pois o metodo esta implementado na minha class, como vou fazer pra add os dados agora com getValueAt retornando null.
Não cara, vc não entendeu. Volta a implementação do getValueAt como tava antes que tava certa!
O que eu disse é o seguinte. Você, na sua tela, não vai chamar diretamente o getValueAt nem o setValueAt. Ou seja, no seu botão, jamais haverá algo como:
txtNome.setText(model.getValueAt(0, linha));
E sim algo como:
User user = model.get(linha);
txtNome.setText(user.getNome());
Mas o JTable vai, internamente, chamar esses métodos. Ou seja, o setValueAt e o getValueAt são métodos chamados pelo JTable, não por você. De qualquer forma, você deve fornecer uma implementação para eles, como você já estava fazendo.
Então, mantém o getValueAt como estava, e usa o addUser, que deve funcionar.
A lógica toda do processo é essa aqui:
- Você vai chamar o model.add(usuario);
- Esse método adiciona um usuário na lista, e dispara o evento de que a última linha da tabela foi adicionada;
- Ao ouvir esse evento, o JTable vai chamar o getValueAt, para pedir os valores dessa linha;
- Com os valores em mãos, a linha será desenhada.
package com.table.models;
import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;
import com.model.User;
public class ModelTable extends AbstractTableModel{
//Nessa lista você grava seus usuários
List<User> lista;
private int COLUMN_NOME = 0;
//O telefone fica na coluna 1
private int COLUMN_TEL = 1;
public ModelTable(List<User> usuarios)
{
lista = new ArrayList<User>(usuarios);
}
public ModelTable()
{
this(new ArrayList<User>());
}
@Override
public int getColumnCount() {
return 2; //Ok, são duas colunas
}
@Override
public int getRowCount() {
return lista.size(); //Existirá uma linha na tabela para cada usuário da lista
}
public String getColumnName(int columIndex){
if(columIndex == this.COLUMN_NOME){
return "Usuário";
}
if (columIndex == this.COLUMN_TEL){
return "Telefone";
}
return "Telefone";
}
public void add(User usuario) {
//Adicionamos um usuário na lista
lista.add(usuario);
//Avisamos o JTable que ele deve repintar a última linha
this.fireTableRowsInserted(lista.size()-1, lista.size()-1);
}
@Override
public Object getValueAt(int arg0, int arg1) {
//Aqui informamos para o JTable que dado está em cada linha/coluna da tabela.
User usuario = this.lista.get(rowIndex);
if(this.COLUMN_NOME == columnIndex){
return usuario.getNome(); // vai dar nullPointer aqui...
}
if(this.COLUMN_TEL == columnIndex){
return usuario.getTel();
}
return usuario.getTel();
}
}
Editando aqui pq nao vi vc respondendo acima…
Funcionou perfeitamente aqui…Agora Vini o que nao to entendendo é o seguinte, JTable chama getValueAt na hora que eu seto o model certo? Se sim pq nao ta dando nullPointer pois a lista esta vazia…Quando for executado o metodo getValueAt ainda nao usei o metodo add(), portanto era pra dar nullPointerException n? E eu tb achava q a inserção de dados no Table quem fazia era getValueAt automaticamente…
A lista está vazia, mas está inicializada (foi inicializada no construtor). Ela não está nula.
O getRowCount() irá retornar 0. E o método getValueAt não será chamado.
O setValueAt só vai ser chamado automaticamente se um usuário alterar um campo já exibido na tabela. Aí a tabela chama esse método para avisar o model que isso aconteceu. Logo depois de chamar o setValueAt, ela chama novamente o getValueAt para pintar o valor alterado.
Isso te dá a possibilidade de cancelar uma alteração dentro da setValueAt.
A lista está vazia, mas está inicializada (foi inicializada no construtor). Ela não está nula.O getRowCount() irá retornar 0. E o método getValueAt não será chamado.
O setValueAt só vai ser chamado automaticamente se um usuário alterar um campo já exibido na tabela. Aí a tabela chama esse método para avisar o model que isso aconteceu. Logo depois de chamar o setValueAt, ela chama novamente o getValueAt para pintar o valor alterado.
Isso te dá a possibilidade de cancelar uma alteração dentro da setValueAt.
Entao o getValueAt so é chamado se exisitir alguma linha no Table?
Os parametros passados no metodo this.fireTableRowsInserted(lista.size()-1, lista.size()-1); indicam o que especificadamente?
Você alterou a sua lista, certo? Então vc precisa avisar ao JTable que a lista foi alterada, para que ela pinte a nova linha.
Aqueles parâmetros indicam os índices da primeira e última linhas adicionadas. No caso, como foi só uma linha no final, ambos os índices são iguais ao índice do último elemento da lista.
Você alterou a sua lista, certo? Então vc precisa avisar ao JTable que a lista foi alterada, para que ela pinte a nova linha.Aqueles parâmetros indicam os índices da primeira e última linhas adicionadas. No caso, como foi só uma linha no final, ambos os índices são iguais ao índice do último elemento da lista.
Significa então q sempre q executado o aplicativo se for alterado algo no estado do meu model o proprio Table verifica e faz as alterações, isso com base no getValueAt.
Isso. Ele verifica pq esse “fire” avisa o JTable que alguma coisa mudou. E o que.
Aí o JTable chama o getValueAt para aplicar as mudanças.
Isso. Ele verifica pq esse “fire” avisa o JTable que alguma coisa mudou. E o que.Aí o JTable chama o getValueAt para aplicar as mudanças.
Pôo Vini, muito obrigado mais uma vez pelos posts e pela paciencia, em fim entendi rsrsrs.
Se a idéia é não usar o DefaultTableModel, a minha paciência é virtualmente infinita…
kkkkk bom saber disso, além do mais eu fugi do DefaultTableModel por sua causa kkk.
Mas vai dizer que não é melhor fazer:
model.add(usuario)
Do que:
model.addRow(new Object[] {usuario.getNome(), usuario.getTelefone()});
Fora que, se vc trocar a ordem das colunas, ou se uma coluna nova surgir, vc não precisará alterar nada além do model…
Mas vai dizer que não é melhor fazer:
model.add(usuario)Do que:
model.addRow(new Object[] {usuario.getNome(), usuario.getTelefone()});Fora que, se vc trocar a ordem das colunas, ou se uma coluna nova surgir, vc não precisará alterar nada além do model…
kkkkkk Graças á Deus, e ao seu movimento de extinçao do DefaultTableModel, não cheguei á usa-lo muito :D.