如何维持细胞编辑后的JTable细胞呈现

问题描述:

你们是在点我在我的最后一个问题的正确方向,真棒,我有几分我原来的问题的延伸位置:如何维持细胞编辑后的JTable细胞呈现

How to set a JTable column as String and sort as Double?

正如我现在通过使用自定义单元格渲染器将我的价格列格式化为$ ###,## 0.00,现在我也为单元格设置了一个JTextField编辑器。单元格的编辑工作得很好,除了值更新时,在我的自定义渲染器中设置的数字格式不再像格式化单元格(我放弃$ after编辑提交后)。即使在初始显示数据之后,该渲染器是否应该渲染单元格?

我曾尝试使用没有运气以下:

((AbstractTableModel) table.getModel()).fireTableDataChanged(); 

我希望这将迫使表,可以使用自定义渲染呈现新的价值观重新验证并重新绘制细胞,但这个不幸没有工作...

我错过了什么......显然,但是什么?

当编辑器结束时,表格的editingStopped()方法通过getCellEditorValue()收集新值,并将其用于模型中的setValueAt()。该模型反过来应该是fireTableCellUpdated(),它将调用指定的渲染器。扩展default应该足以处理Number格式。在其他情况下,使用渲染器的实例作为编辑器组件可能会很方便;这example显示了一个典型的实现。

附录:这是一个使用默认编辑器和渲染器实现的基本示例。

附录:感谢来自@mKorbel的有用评论,我已更新示例以选择单元格的文本进行编辑,如@ camickr的文章Table Select All Editor中所述。

RenderEditNumber

package overflow; 

import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.event.MouseEvent; 
import java.text.NumberFormat; 
import java.util.EventObject; 
import javax.swing.DefaultCellEditor; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.JTextField; 
import javax.swing.table.DefaultTableCellRenderer; 
import javax.swing.table.DefaultTableModel; 
import javax.swing.text.JTextComponent; 

/** @see http://*.com/a/10067560/230513 */ 
public class RenderEditNumber extends JPanel { 

    private NumberFormat nf = NumberFormat.getCurrencyInstance(); 

    public RenderEditNumber() { 
     DefaultTableModel model = new DefaultTableModel(
      new String[]{"Amount"}, 0) { 

      @Override 
      public Class<?> getColumnClass(int columnIndex) { 
       return Double.class; 
      } 
     }; 
     for (int i = 0; i < 16; i++) { 
      model.addRow(new Object[]{Double.valueOf(i)}); 
     } 
     JTable table = new JTable(model) { 

      @Override // Always selectAll() 
      public boolean editCellAt(int row, int column, EventObject e) { 
       boolean result = super.editCellAt(row, column, e); 
       final Component editor = getEditorComponent(); 
       if (editor == null || !(editor instanceof JTextComponent)) { 
        return result; 
       } 
       if (e instanceof MouseEvent) { 
        EventQueue.invokeLater(new Runnable() { 

         @Override 
         public void run() { 
          ((JTextComponent) editor).selectAll(); 
         } 
        }); 
       } else { 
        ((JTextComponent) editor).selectAll(); 
       } 
       return result; 
      } 
     }; 
     table.setPreferredScrollableViewportSize(new Dimension(123, 123)); 
     table.setDefaultRenderer(Double.class, new CurrencyRenderer(nf)); 
     table.setDefaultEditor(Double.class, new CurrencyEditor(nf)); 
     this.add(new JScrollPane(table)); 
    } 

    private static class CurrencyRenderer extends DefaultTableCellRenderer { 

     private NumberFormat formatter; 

     public CurrencyRenderer(NumberFormat formatter) { 
      this.formatter = formatter; 
      this.setHorizontalAlignment(JLabel.RIGHT); 
     } 

     @Override 
     public void setValue(Object value) { 
      setText((value == null) ? "" : formatter.format(value)); 
     } 
    } 

    private static class CurrencyEditor extends DefaultCellEditor { 

     private NumberFormat formatter; 
     private JTextField textField; 

     public CurrencyEditor(NumberFormat formatter) { 
      super(new JTextField()); 
      this.formatter = formatter; 
      this.textField = (JTextField) this.getComponent(); 
      textField.setHorizontalAlignment(JTextField.RIGHT); 
      textField.setBorder(null); 
     } 

     @Override 
     public Object getCellEditorValue() { 
      try { 
       return new Double(textField.getText()); 
      } catch (NumberFormatException e) { 
       return Double.valueOf(0); 
      } 
     } 

     @Override 
     public Component getTableCellEditorComponent(JTable table, 
      Object value, boolean isSelected, int row, int column) { 
      textField.setText((value == null) 
       ? "" : formatter.format((Double) value)); 
      return textField; 
     } 
    } 

    private void display() { 
     JFrame f = new JFrame("RenderEditNumber"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(this); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new RenderEditNumber().display(); 
      } 
     }); 
    } 
} 
+0

+1,但我看到,如果你想添加,删除或编辑存在的价值无法正常工作之前,编辑器返回0.00 :-),我得看看...... – mKorbel 2012-04-09 14:39:52

+0

好点。对于矩阵输入,编辑器故意在'NumberFormatException'上返回零; 'cancelCellEditing()'将是一个更普遍的选择。 – trashgod 2012-04-09 17:42:15

+0

这与JFormattedTextField或JSpinner相同,因为CellEditor,我确定Rob得到了...,那你必须返回Document,Rob你在哪里:-) – mKorbel 2012-04-09 17:48:09