Re:Ação no modelo de JTable

Por que na implementação do seu setValueAt do model você não altera os dois valores?

[quote=diogoroos]Exceção de índice… vou colocar novamente o TableModelListener para ver exatamente o erro e posto. Você teria um exemplo para eu ver se estou fazendo da maneira correta ?
-Valeu pela atenção.[/quote]

Como assim “exceção de índice”. Você tem um model próprio?

A idéia é atualizar duas propriedades do seu objeto, ao invés de uma. Então é só fazer isso!

[code]
public class SampleTableModel extends AbstractTableModel

public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex == COL_VALOR_ORIGINAL) {
valores.get(rowIndex).setValorOriginal((Double)value);
valores.get(rowIndex).setValorAberto((Double)value);
}
}[/code]

Valores seria um JList com sua classe, seja ela qual for.

Basta fazer:

[code]public class SampleTableModel extends AbstractTableModel {

public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex == COL_VALOR_ORIGINAL) {
valores.get(rowIndex).setValorOriginal((Double)value);
valores.get(rowIndex).setValorAberto((Double)value);
}
}

public Class <?> getColumnClass(int columnIndex) {
if (columnIndex == COL_CHECK) //Índice da coluna com checkbox
return Boolean.class;
return Object.class; //Demais colunas
}
}[/code]

Não deixe de ler esses ótimos artigos sobre o assunto:
http://www.informit.com/articles/article.aspx?p=332278
http://www.informit.com/articles/article.aspx?p=333472

Você não vai se arrepender. Usar um model próprio evita duplicação de dados, deixa o código mais limpo, mais organizado e mais fácil.

Você já leu os artigos que eu te passei?

Olha só.

Suponha que vc tenha a classe:

public class TitulosDoMain { public double getValorOriginal(); public void setValorOriginal(double valor); public double getValorAberto(); public void setValorAberto(double valor); }

Aqui não coloquei implementação. Mas suponha que esses gets e sets funcionam.

Aí vc cria o seu TableModel. Ele vai trabalhar diretamente com uma lista de TitulosDoMains. A mesma que vc obtém do seu ServerFacade.

Vamos supor que vc queira para coluna 0 o valor Original e para coluna 1 o valor aberto.

[code]public class TitulosTableModel extends AbstractTableModel {
private static final int COL_VALOR_ORIGINAL = 0;
private static final int COL_VALOR_ABERTO = 1;

private List&lt;TitulosDoMain&gt; valores;       

public TitulosTableModel(List&lt;TitulosDoMain&gt; valores) {
      this.valores = new ArrayList&lt;TitulosDoMain&gt;(valores);
}

public int getRowCount() {
    //Quantas linhas tem sua tabela? Uma cada item da lista.
    return valores.size();
}

public int getColumnCount() {
    //Quantas colunas tem a tabela? Nesse exemplo, só 2.
    return 2;
}

public String getColumnName(int columnIndex) {
    //Qual é o nome das nossas colunas?
    if (column == COL_VALOR_ORIGINAL) return "Valor orig.";
    if (column == COL_VALOR_ABERTO) return "Valor aberto";
}

public Object getValueAt(int row, int column) {
    //Precisamos retornar o valor da coluna column e da linha row.
    TitulosDoMain titulo = valores.get(row);
    if (column == COL_VALOR_ORIGINAL) return titulo.getValorOriginal();
    else if (column == COL_VALOR_ABERTO) return titulo.getValorAberto();
}

public  void setValueAt(Object aValue, int rowIndex, int columnIndex) {
    //Vamos alterar o valor da coluna columnIndex na linha rowIndex com o valor aValue passado no parâmetro.
    //Note que vc poderia alterar 2 campos ao invés de um só.
    if (column == COL_VALOR_ORIGINAL) titulo.setValorOriginal(Double.parseDouble(aValue.toString()));
    else if (column == COL_VALOR_ABERTO) titulo.setValorAberto(Double.parseDouble(aValue.toString()));
}

public  Class getColumnClass(int columnIndex) {
    //Qual a classe das nossas colunas? Nesse caso, é double.
    return Double.class;
}

boolean isCellEditable(int rowIndex, int columnIndex) {
    //Indicamos se a célula da rowIndex e da columnIndex é editável. Nossa tabela toda é.
    return true;
}

}
[/code]

Agora, para fazer sua tabela, faça só:

O ideal ainda seria adicionar métodos para inserir e remover títulos do seu modelo. Para isso, você terá que usar os eventos para avisar a tabela que isso ocorreu. Os eventos chamam-se fireTableRowInserted, fireTableRowRemove. Um exemplo:

public void addTitulo(TitulosDoMain titulo) { valores.add(titulo); //Informamos que a última linha foi adicionada. fireTableRowInserted(valores.size()-1, valores.size()-1); }

O que vc tem que entender é que quem chama os métodos do model é a tabela. É a forma dela perguntar para o seu programa o que colocar em seu interior.
Ela diz “Estou desenhando a linha row e coluna col. Que valor tem aí?”. Mas ela faz isso através do método getValueAt.

Da mesma forma, quando alguém edita sua tabela, ela diz:
“Ei! Editaram uma das células. É a de linha rowIndex e coluna columnIndex. O objeto, já com a modificação é esse aValue aqui.”. Ela faz isso através do setValueAt. Então, vc atualiza o seu modelo, se achar que deve.

A regra é:

  1. A tabela desenha dados, mas não sabe que dados são esses;
  2. O modelo é quem sabe a respeito dos dados;

Bom dia pessoal.
–Até vi alguns tópicos criados aqui e em outros fóruns mas a solução para este problema não ficou clara.
Queria saber se vocês já conseguiram implementar uma alteração em uma célula X enquanto digita-se algo em determinada célula.
Preciso de algo parecido com este abaixo, porém para células de uma JTable:

keyReleased(KeyEvent kr) {
		if(kr.getSource() == textVlroriginal) {
			if(textVlroriginal.getText().length() > 0) {
				textVlrAberto.setText(textVlroriginal.getText()); // alterar o textVlraberto enquanto for digitado algo no textVlroriginal
			}
		}
	}

Sei que tem que implementar o TableModelListener e as ações devem ser no Model, e não na JTable, mas já quebrei a cabeça e não consegui. O máximo que consegui desta maneira foi mostrar uma msg dizendo que houve uma alteração na célula (TableModel.UPDATE), mas o valor é alterado para o que estava anteriormente após a msg. Tentei um setValueAt no evento do Model mas não consegue encontrar a linha/coluna que especifiquei e dá exceção.
Valeu!

Exceção de índice… vou colocar novamente o TableModelListener para ver exatamente o erro e posto. Você teria um exemplo para eu ver se estou fazendo da maneira correta ?
-Valeu pela atenção.

[quote=ViniGodoy][quote=diogoroos]Exceção de índice… vou colocar novamente o TableModelListener para ver exatamente o erro e posto. Você teria um exemplo para eu ver se estou fazendo da maneira correta ?
-Valeu pela atenção.[/quote]

Como assim “exceção de índice”. Você tem um model próprio?

A idéia é atualizar duas propriedades do seu objeto, ao invés de uma. Então é só fazer isso!

[code]
public class SampleTableModel extends AbstractTableModel

public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex == COL_VALOR_ORIGINAL) {
valores.get(rowIndex).setValorOriginal((Double)value);
valores.get(rowIndex).setValorAberto((Double)value);
}
}[/code]

Valores seria um JList com sua classe, seja ela qual for.[/quote]

Estou usando DefaultTableModel pq ainda não consegui criar um AbstractTableModel com JCheckBox…
-Obrigado pelo exemplo.

[quote=ViniGodoy]Basta fazer:

[code]public class SampleTableModel extends AbstractTableModel {

public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex == COL_VALOR_ORIGINAL) {
valores.get(rowIndex).setValorOriginal((Double)value);
valores.get(rowIndex).setValorAberto((Double)value);
}
}

public Class <?> getColumnClass(int columnIndex) {
if (columnIndex == COL_CHECK) //Índice da coluna com checkbox
return Boolean.class;
return Object.class; //Demais colunas
}
}[/code]
[/quote]

Obrigado Vinícius!

Desculpe a ignorância a respeito, estou tentando implenetar a classe com um modelo AbstractTableModel mas ainda não consegui. O que seria setValorOriginal ?

A forma que estou utilizando o DefaultTableModel é a seguinte:

public DefaultTableModel getModelEmpresas() {
		String[] titles = new String[] { "Selecionado", "VlrAberto", "VlrOriginal", "Resultado"};
		return new DefaultTableModel(new Object[][]{}, titles) {
			private static final long serialVersionUID = 1L;
			@SuppressWarnings("unchecked")
			Class[] types = new Class[] { java.lang.Boolean.class, java.lang.Object.class,
					java.lang.Object.class, java.lang.Object.class};
			boolean[] canEdit = new boolean[] { true, false, true, true};

			@SuppressWarnings("unchecked")
			public Class getColumnClass(int columnIndex) {
				return types[columnIndex];
			}
			public boolean isCellEditable(int rowIndex, int columnIndex) {
				return canEdit[columnIndex];
			}
		};
	}

E para popular a tabela eu faço:

TITULOSDOMAIN titulos = new TITULOSDOMAIN();
List&lt;TITULOSDOMAIN&gt; listagem = ServerFacade.getInstance().findTITULOS(titulos); //recebe a lista de titulos do banco
DefaultTableModel modelo = (DefaultTableModel)tableTitulos.getModel();
modelo.setRowCount(0);
for (TITULOSDOMAIN titulos: listagem) {
	modelo.addRow(mountRows(empresas)); //mountRows retorna um vector com as linhas preenchidas
}
tableTitulos.setModel(modelo);

Se não for pedir demais, como ficaria com AbstractTableModel ao invés de DefaultTableModel ?

Muito obrigado mais uma vez.