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<TitulosDoMain> valores;
public TitulosTableModel(List<TitulosDoMain> valores) {
this.valores = new ArrayList<TitulosDoMain>(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 é:
- A tabela desenha dados, mas não sabe que dados são esses;
- 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<TITULOSDOMAIN> 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.