[Resolvido] JTable não retorna a linha selecionada

9 respostas Resolvido
java-sejtablearraylist
M

Galera, boa tarde e um feliz ano novo.

Minha aplicação está me retornando uma exceção, e estou tentando entender o motivo, eu tenho o seguinte evento dentro de uma JTable.

private void tbCidadesMouseClicked(java.awt.event.MouseEvent evt) {

Cidade c = new Cidade();
    CidadeDao dao = new CidadeDao();
    
    int row = tbCidades.getSelectedRow(); //Pego a linha selecionada.
    int id = Integer.parseInt(tbCidades.getValueAt(row, 0).toString()); // passo o valor da Id para a variavél id.
    
    c.setIdCidade(id);//seto o objeto com o valor da id;
    
    int index = dao.listar().indexOf(c); //procuro dentro do ArrayList a verdadeira posição do Objeto.
    c = dao.listar().get(index); // retorno de dentro do arrayList o objeto da classe cidade.
    
    System.out.println(dao.listar().contains(c));//Exibo uma mensagem se existe dentro do arrayList

    
    if(index>=0){
        c = dao.listar().get(index);
        
        setarCampos(c);
        habilitaCampos();
        btGravar.setEnabled(false);
        btAlterar.setEnabled(true);
        btExcluir.setEnabled(true);
    }        
}

Conforme eu vou selecionando as linhas dentro da JTable, os campos de texto vão sendo setados de acordo com o objeto, porém em determinados objetos ele gera uma exceção do tipo java.lang.ArrayIndexOutOfBoundsException: -1

Eu entendo que essa exceção significa uma posição errada dentro do ArrayList, que a linha na JTable não foi selecionada e retorna -1 para o ArrayList, porém essa linha é selecionada dentro da JTable, o que pode estar acontecendo?

9 Respostas

S

1 - você deveria utilizar um ListSelectionListener para tratar seleções na JTable.

2 - você sempre está criando um novo objeto Cidade e procurando ele dentro da sua lista, se ele foi recém criado, ele não estará na lista e o dao.listar().indexOf(c) retornará -1.

3 - você chama 4 vezes o dao.listar(), deveria chamar só uma vez e armazenar a lista em uma variável local.

4 - implemente o seu proprio TableModel e renderize os elementos da lista retornada pelo seu DAO, aí, quando quiser obter um objeto da lista, basta você fazer:

int posicao = minhaTable.getSelectedIndex();
Cliente cliente = minhaLista.get(posicao);
M

A parte estranha é que essa linha de código:

int row = tbCidades.getSelectedRow(); //Pego a linha selecionada.

retorna pra mim todas as linhas da JTable, o problema é quando vou buscar esse elemento dentro do ArrayList:

int row = tbCidades.getSelectedRow();
Cidade cidade = minhaLista.get(row);

Eles seleciona cerca de 120 objetos dentro do arrayList, depois disso ele já volta a retornar o erro, percebi que dentro do meu arrayList existe sub-listas preenchidas de 0 a 99, 100 a 199, 200 a 299 e assim por diante, será que ele só busca na primeira lista?

S

Não, ela retorna somente o índice da linha selecionada, se não houver seleção, retorna -1.

Um ArrayList não seleciona nada, é só uma coleção de objetos.

Essas “sub-listas” que você notou são arrays, são a estrutura de dados utilizada internamente pelo ArrayList.
Um LinkedList utiliza elos encadeados para armazenar seu conteúdo.
Um ArrayList utiliza arrays, por isso se chama ArrayList.

M

Muito obrigado por essas informações, vou modificar o código aqui.

M

Ainda continuo com o erro, eu parei de carregar minha JTable utilizando o DefaultTableModel, e estou utilizando o AbstractTableModel, o meu método de setar campos funciona até determinada linha, depois aparece o erro:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException

Minha função para setar os campos está dessa forma:

private void setarCampos(){
        indice = tbEstados.getSelectedRow();
        
        PaisDao daoP = new PaisDao();
        EstadoDao dao = new EstadoDao();
        
        ArrayList<Estado> estados = new ArrayList<>(dao.listar());
        ArrayList<Pais> paises = new ArrayList<>(daoP.listar());
        
        txtCod.setText(tbEstados.getValueAt(indice, 0).toString());
        txtNome.setText(tbEstados.getValueAt(indice, 1).toString());
        txtSigla.setText(tbEstados.getValueAt(indice, 2).toString());
        
        Estado e = new Estado(Integer.parseInt(tbEstados.getValueAt(indice, 0).toString()), null, tbEstados.getValueAt(indice, 1).toString(), tbEstados.getValueAt(indice, 2).toString());
        e = estados.get(indice);
        
        for(Pais p: paises){
            if(e.getFkIdPais().equals(p.getIdPais())){
                cbBoxPais.setSelectedItem(p.getNome());
            }
        }
    }

Não consegui utilizar o

Alguém pode ajudar?

L

amigo, pra carregar esta tabela de cidades vc ta usando o AbstractModel ou DefaultTableModel?

Eu tive um problema parecido aqui, no meu caso, no java o indice sempre começa em 0,
mas no Banco de dados Postgres os indi8ces comeca em 1…
eu resolvi colocando +1 na variavel que armazenava o indice…

M

Estou utilizando o AbstractModel, acredito que o problema seja estouro de memória, afinal dentro deste ArrayList existe mais de 10.000 registros, fiz a mesma pesquisa porém com ResultSet rs utilizando o método absotule(int row), não ocorreu nenhum problema durante o processo.

S
Solucao aceita

Quando postar seu código, sempre selecione ele e clique no botão </> pra deixar formatado corretamente.

Não crie novas listas, seu DAO já retornam listas, é só referenciá-las diretamente.

Você já tem a lista de estados na mão, é só obter o estado da posição indice e usar ele para popular os JTextFields, não há necessidade de pegar os dados da JTable.

Aqui você instancia um estado para logo em seguida matá-lo e obter o estado da posição indice, não faz sentido.

Sem ver o código completo de suas classes, fica complicado te orientar da melhor forma.
Eu faria algo mais ou menos assim:

private void setarCampos(){
    PaisDao paisDao = new PaisDao();
    EstadoDao estadoDao = new EstadoDao();
    
    List<Estado> estados = estadoDao.listar();
    List<Pais> paises = paisDao.listar();
    
    comboBoxModelPaises.setPaises(paises);
    tableModelEstados.setEstados(estados);
	
    int indiceEstado = tableEstados.getSelectedRow();

    Estado estado = estados.get(indiceEstado);
    Pais pais = estado.getPais();

    cbBoxPais.setSelectedItem(pais.getNome());
	
    txtCod.setText(estado.getCodigo());
    txtNome.setText(estado.getNome());
    txtSigla.setText(estado.getSigla());
}
M

Rapaz, incrível o que a falta de experiencia faz, todos os dicas funcionaram perfeitamente bem, obrigado.

Criado 31 de dezembro de 2017
Ultima resposta 8 de jan. de 2018
Respostas 9
Participantes 3