Para não usar DefaultTableModel, tô seguindo a dica do Ironlynx, usando o ObjectTableModel do projeto Towell, mas não consigo fazer aparecer nas colunas da minha JTable, um JTextField que eu fiz que formata os números para decimal.Tenho 3 colunas(A,B e Media) que recebem meus JTextField, sendo que as duas primeiras eu posso editar, faço um cálculo com as duas primeiras(usando BigDecimal) e exibo a média na terceira após pressionar um botão.Alguem pode me ajudar?
Poste seu código.
[code]
private JTable getJTable(){
model = new ObjectTableModel(
new AnnotationResolver(Calculo.class), “entrada1,entrada2,Media”);
if (table == null) {
table = new JTable();
table.setModel(model);
table.setDefaultRenderer(Object.class, new MyCellRenderer());
TableColumn column1 = table.getColumnModel().getColumn(0);
column1.setCellEditor(new DefaultCellEditor(new JNumberField()));
TableColumn column2 = table.getColumnModel().getColumn(1);
column2.setCellEditor(new DefaultCellEditor(new JNumberField()));
model.setColEditable(0, true);
model.setColEditable(1, true);
List<Calculo> listaC=new CalculoDao().listarCalculos();
model.setData(listaC);
btnCalc.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
// Calculos c = model.getValue(table.getSelectedRow()); e códgos de ação do botão...
table.updateUI();
}//fim do método actionperformed do botão de comparação
});
}
return table;
}[/code]
testei isoladamente o meu JNumberField e ele funciona OK fora da JTable.Alguma idéia???
Associe pelo setDefaultRenderer para a Class que voce quer.
Associe pelo setDefaultRenderer para a Class que voce quer.
Eu retirei o renderer e exibiu o JTextField com os dados!Mas eu tenho problemas para editar os valores!Sempre recebo uns errros:
java.lang.RuntimeException: java.lang.IllegalArgumentException: Can not set java.math.BigDecimal field com.testes.Calculo.entrada1 to java.lang.String
at com.towel.el.handler.FieldHandler.setValue(FieldHandler.java:73)
at com.towel.el.FieldResolver.setValue(FieldResolver.java:91)
at com.towel.swing.table.ObjectTableModel.setValueAt(ObjectTableModel.java:142)
Como eu resolvo isso se para editar eu tenho sempre que ter uma string?Obrigado pela atenção.
PaulH,
vc DEVE fazer o que o marky falou.Lembre-se que vc edita uma String mas faz operações com o BigDecimal.Basicamente, BigDecimal->String(manipula)->BigDecimal(faz operações/cálculos)->String(exibe), e assim sucessivamente.
Ironlynx,
não entendi.Eu tenho que botar a BigDecimal no renderer é isso?Eu sei que quando eu manipulo o textfield só posso fazer como String, mas vem da base como Decimal(como é salvo no BD), vai para BigDecimal, de BD para o JTextField, vai para BD para executar os calculos e volta para String para exibir.OK, eu entendi a teoria, mas não a prática…pode explicar com código, por favor? :oops:
PaulH,
leia esse tópico:
http://www.guj.com.br/java/277369-jtable-com-celulas-jtextfield
Preste muita atenção nos passos descritos pelo ViniGodoy.É o que vc precisa.
Eu não entendi bem… eu faço o editor da JTable recebendo o meu JtextField, mas como eu faço isso se meu JTextField recebe parâmetros para ter o tamanho do numero e a quantidade de decimais?E eu passo BigDecimal.class para o setDefaultEditor???Eu uso o ObjectTableModel, não dará problema?
PaulH,
não tem mistério, mesmo com o ObjectTableModel!
adicione seu editor:
TableColumn col = table.getColumnModel().getColumn(suaColunaIndex);
col.setCellEditor(new MyTableCellEditor());
Vc usa um JtextField personalizado, certo?
Vamos pegar esse aqui do Dyorgio nesse tópico:
http://www.guj.com.br/java/272708-mascara-para-jtextfield-valor-real
seu TableCellEditor(daqui: http://www.exampledepot.com/egs/javax.swing.table/CustEdit.html)
[code]
public class MyTableCellEditor extends AbstractCellEditor implements TableCellEditor {
// This is the component that will handle the editing of the cell value
JComponent component = new JNumberFormatField();
// This method is called when a cell value is edited by the user.
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int rowIndex, int vColIndex) {
// 'value' is value contained in the cell located at (rowIndex, vColIndex)
if (isSelected) {
// cell (and perhaps other cells) are selected
}
// Configure the component with the specified value
((JTextField)component).setText((String)value);
// Return the configured component
return component;
}
// This method is called when editing is completed.
// It must return the new value to be stored in the cell.
public Object getCellEditorValue() {
return ((JTextField)component).getText();
}
}[/code]
Ah!Vc precisa que seu JtextField receba parâmetros para quantidade de casas decimais, certo???
Só mudar o Construtor de MyTableCellEditor. para aceitar um parâmetro inteiro e passe para o
JNumberFormatField que já tem até um construtor para isso!Não testei nada, apenas li o que estava nos links, mas não tem mistério.Testa aí.
Cara, QUASE funcionou!
O meu problema é que diferentes registros (linhas da minha JTable) tem diferentes cálculos registrados, como:
1,2 e 1,4
234,911 e 456,789
Sacou?A formatação muda de uma linha para outra(com uma casa decimal e com três).E para piorar, formatando eu perco a capacidade de colorir o menor/maior como eu estava fazendo.Pesquisei no google, mas nunca vi formatação multilinhas na jtable, se tiver uma dica, eu aceito!E obrigado pelo código!
1,2 e 1,4
234,911 e 456,789
Nossa…ferrou pra vc!A formatação é feita Coluna a Coluna.Vc tem linhas com diferentes formatações(e ainda precisa abrir para edição e comparação!).O tratamento célula a célula é muito deficiente na JTable(infelizmente!)
Talvez manipulando o método getCellRenderer lhe ajude, mas não é garantido.
Nossa que droga, não estou tendo sucesso com o getCellRenderer…
É muito complicado essa formatação.Pena não ter algo mais fácil…
Preciso de algo parecido com isso para um projetinho aqui.Vou sentar e pensar como fazer, mas não é fácil o fato de ter que ->formatar para JTextfield->Muda para BigDecimal/Double/whatever->executa operações ->formata JtextField de novo para cada célula para ser exibido.Se eu conseguir resolver de uma forma decente eu posto aqu para você.
Iron, fiz como vc me ensinou, mas só a última formatação fica na coluna TODA!Era para a primeira ficar com duas e a segunda com três casas decimais.
casas, mas só ficam as duas com três casas decimais!
Pego as colunas do model:
TableColumn coluna1 = table.getColumnModel().getColumn(1);
TableColumn coluna2 = table.getColumnModel().getColumn(2);
TableColumn coluna3 = table.getColumnModel().getColumn(3);
for(int j=0;j<listaC.size();j++){
Calculo cadastrado=listaC.get(j);
coluna1.setCellEditor(new FormatTableCellEditor(cadastrado.getRange(),j));
coluna2.setCellEditor(new FormatTableCellEditor(cadastrado.getRange(),j));
coluna3.setCellEditor(new FormatTableCellEditor(cadastrado.getRange(),j));
}
E o formatador como você me passou:
[code]
public class FormatTableCellEditor extends AbstractCellEditor implements TableCellEditor{
JComponent component =null;
int linha=0;
public FormatTableCellEditor(int range,int row){
this.linha=row;
if(range==5){
component = new JNumberFormatField(new DecimalFormat("#,##0.00000")){{setLimit(11);}};
}else if(range==4){
component = new JNumberFormatField(new DecimalFormat("#,##0.0000")){{setLimit(10);}};
}else if(range==3){
component = new JNumberFormatField(new DecimalFormat("#,##0.000")){{setLimit(9);}};
}else if(range==2){
component = new JNumberFormatField(new DecimalFormat("#,##0.00")){{setLimit(8);}};
}else if(range==1){
component = new JNumberFormatField(new DecimalFormat("#,##0.0")){{setLimit(8);}};
}
}
// This method is called when a cell value is edited by the user.
public Component getTableCellEditorComponent(JTable table, Object value,boolean isSelected, int rowIndex, int vColIndex) {
// 'value' is value contained in the cell located at (rowIndex, vColIndex)
if (isSelected) {
}
if(linha==rowIndex){//linha selecionada
// Configure the component with the specified value
((JTextField)component).setText((String)value);
}
// Return the configured component
return component;
}
// This method is called when editing is completed.
// It must return the new value to be stored in the cell.
public Object getCellEditorValue() {
return ((JTextField)component).getText();
}
}[/code]
Porque só pega o último range e atualiza a coluna toda com esse range???
PaulH,
é fácil o porquê de não funcionar.Voce continua formatando apenas por COLUNA.Para lidar diretamente com a célula, vc precisa lidar diretamente com o método getTableCellEditorComponent() para nele, trabalhar célula a célula.Passe sua lista para o seu CellEditor componente para dentro dele, trabalhar com as células.Ou seja:
instalando nas colunas:
coluna1.setCellEditor(new FormatTableCellEditor(suaLista));
coluna2.setCellEditor(new FormatTableCellEditor(suaLista));
coluna3.setCellEditor(new FormatTableCellEditor(suaLista));
Na sua classe que herda de AbstractCellEditor ponha esse construtor:
public FormatTableCellEditor(List<Calculo> l){
super();
this.lista=l;//não esqueça de declarar sua lista
}
E um método para controlar a sua escala, igual ao que vc fazia no construtor mas que lida diretamente com seu JComponent:
public JComponent formatarCampo(int range){
JComponent component=null;
if(range==5){
component = new JNumberFormatField(new DecimalFormat("#,##0.00000")){{setLimit(11);}};
}else if(range==4){
component = new JNumberFormatField(new DecimalFormat("#,##0.0000")){{setLimit(10);}};
}else if(range==3){
component = new JNumberFormatField(new DecimalFormat("#,##0.000")){{setLimit(9);}};
}else if(range==2){
component = new JNumberFormatField(new DecimalFormat("#,##0.00")){{setLimit(8);}};
}else if(range==1){
component = new JNumberFormatField(new DecimalFormat("#,##0.0")){{setLimit(8);}};
}
return component;
}
Depois é só acertar o seu getTableCellEditorComponent para lidar com as células individualmente:
[code]
public Component getTableCellEditorComponent(JTable table, Object value,boolean isSelected, int rowIndex, int vColIndex) {
if (isSelected) {
}
for(int j=0;j<lista.size();j++){
Calculo cadastrado=lista.get(j);
if(j==rowIndex){//compara com a linha
component= formatarCampo(cadastrado.getRange());
}
}
((JTextField)component).setText((String)value);
return component;
}
} [/code]
Deve funcionar. >
Cara, muuito obrigado!
Ficou perfeito!