Como re-ordenar um AbstractTableModel

8 respostas
ricardospinoza

Pessoal,

Eu tenho um JTable e pretendo adicionar dois botões "Up" e "Down" para permitir ao usuário fazer re-positionamento de itens na table.

JTable tblDetalhe = new JTable();
AbstractTableModel atm = (AbstractTableModel) this.tblDetalhe.getModel();

Li no aqui no fórum que o jtable trabalha com manipulação dos objetos via model, e a manipulação dos objetos ocorre toda por ele.

Ao trangos e barrancos, montei um lego com exemplos que fui encontrando pelo google a fora.

Imagine que a jtable está populada, e que mágicamente o evento do botão chamou meu método abaixo :slight_smile:

public void actionPerformed(ActionEvent e) {
         //aqui cato o item selecionado. pelo menos no bug está apontando para a posição correspondente :-)
         int moveMe = tblDetalhe.getSelectedRows()[0];

         //ai tenho dois métodos marotos para fazer o up ou o down de acordo com o botão pressionado.

         if (e.getSource().equals(this.btnUpItem)) {
			//UP ARROW BUTTON
		    if (moveMe != 0) {     
		    //not already at top
		        swap(moveMe, moveMe-1);
		        tblDetalhe.setSelectionMode(moveMe-1);
		        //tblDetalhe.ensureIndexIsVisible(moveMe-1);
		    }
		}
    	
        if (e.getSource().equals(this.btnDownItem)) {
			//DOWN ARROW BUTTON
		    if (moveMe != tblDetalhe.getModel().getRowCount()-1) {
		    	//not already at bottom
		        swap(moveMe, moveMe+1);
		        tblDetalhe.setSelectionMode(moveMe+1);
		        //list.ensureIndexIsVisible(moveMe+1);
		    }
        }
}

o pulo do gato é o método swap - que deve fazer o troca-a-troca dos itens:

private void swap(int a, int b) {
    	
    	TableModel model = tblDetalhe.getModel();
    	
    	Object aObject = null;
    	Object bObject = null;
    	int aLin = -1, aCol = -1;
    	int bLin = -1, bCol = -1;
    	
    	for (int lin = 0 ; lin < model.getRowCount(); lin++) {
    		
    		for(int col = 0 ; col < model.getColumnCount(); col++) {    			
    			System.out.println("item["+model.getValueAt(lin, col)+"]");
    			
    			if (lin == a) {
    				//System.out.println("elemento a["+model.getValueAt(lin, col)+"]");
    				aObject = tblDetalhe.getValueAt(lin, col);
    				aLin = lin;
    				aCol = col;
    			}
    			
    			if (lin == b) {
    				//System.out.println("elemento b["+model.getValueAt(lin, col)+"]");
    		                bObject = tblDetalhe.getValueAt(lin, col);
    		                bLin = lin;
    				bCol = col;
    			}
    		}//end for col
    	}//end for lin
       //a intenção neste trecho é realizar a troca dos valores.
       if (aObject != null && bObject!=null) {
          model.setValueAt(aObject, bLin, bCol);
          model.setValueAt(bObject, aLin, aCol);
       }
   }

8 Respostas

ricardospinoza

Debugando e lendo a api vi que o método boolean isCellEditable retorna false, ou seja. não permite editar. Acho que é por isto que o método model.setValueAt não está funfando.

Como é que eu desbloqueio da célula pra editar?

CristianPalmaSola10

Para deixar as celulas da jTable serem editas basta sobrescrever o metodo isCellEditable e faze-lo retornar true quando necessario, ai a edicao do texto da celula sera permitido e entaum tera que rescrever o metodo setValueAt para guardar o novo valor

mas para jogar a linha para cima ou para biaxo naum precisa habilitar a edicao de celulas da jTable, basta voce guardar a posicao da linha que o usuario que trocar de posicao remove-la da jTable e adiciona-la novamente na jTable uma posica acima ou abaixo dependendo do que o usuario escolheu ententeu?

CristianPalmaSola10
public void linhaCima(int pos)
    {
        Object o = lista.get(pos);
        lista.remove(pos);
        fireTableRowsDeleted(pos, pos);

        lista.add(pos - 1, o);
        fireTableRowsInserted(pos - 1, pos - 1);
    }

    public void linhaBaixo(int pos)
    {
        Object o = lista.get(pos);
        lista.remove(pos);
        fireTableRowsDeleted(pos, pos);

        lista.add(pos + 1, o);
        fireTableRowsInserted(pos + 1, pos + 1);
    }

Esse código faz o que voce quer, so falta implementar uma validações para evitar que acontece o erro de acesso a indice inexistente

ricardospinoza

Olá Cristian, obrigado por responder. vou tentar fazer com base no seu exemplo e sem sobrescrever o método (já que não precisa neh) rs

Uma dúvida vc colocou um lista, ele é uma lista de model? pra eu percorrer os itens eu tô fazendo dois for´s. é assim mesmo?

CristianPalmaSola10

Voce tem que criar um TableModel personalizado aqui no guj tem um tutorial sobre isso procure na sessao de artigos

ricardospinoza

Oi Cristian, obrigado por mais está dica. Eu tenho um datamodel, inclusive consigo percorer ele em um loop e popular um lista de objects. tem alguma maneira de jogar a lista pro datamodel para atualizado. acho que estamos quase fechando o assunto rsrsrs

Nicolas_Fernandes

Opa, ricardospinoza!

Cê já pensou na ideia de realizar uma consulta no banco de dados ordenando do modo que você quer e jogando pro seu TableModel?
Você poderia criar no seu TableModel um método que alterasse toda a estrutura da tabela:

public void alterarConteudoTabela(List<Entidade> lista) {

    this.lista = lista;
    fireTableDataChanged();
}

Que tal?
Espero ter ajudado,
fique com Deus! :D

ricardospinoza

Oi Nicolas. obrigado pela dica. No meu caso eu cato de um xml, e a idéia é depois que o usuário ordenar na interface vou pesistir a sequência pra trazer já prontinha da próxima vez :smiley:

Criado 5 de março de 2012
Ultima resposta 6 de mar. de 2012
Respostas 8
Participantes 3