2017-08-23 77 views
1

我有一個DoubleEditor,我修改了我從網絡中取出的Integer Editor。我正在使用它來驗證在JXTable單元格上輸入的雙精度值,該單元格的值是從0.00100.00。但是,我有這個奇怪的問題:如果我在單元格中輸入1.999,我按下輸入什麼都不會發生。 (I expected it to convert this to 2.00)。如果我點擊編輯值爲1.999的單元格,然後執行轉換。如果我輸入1.9999它立即執行轉換!JTable單元上的Double Value編輯器上的「奇怪」行爲

所有我從這個編輯器需要的是:1)代表我的價值觀10.00和2)必須四捨五入到2d.p任何輸入的值

這裏是代碼:

public class DoubleEditor extends DefaultCellEditor { 

JFormattedTextField ftf; 
DecimalFormat doubleFormat; 
private Double minimum, maximum; 
private boolean DEBUG = false; 

public DoubleEditor(double min, double max) { 
    super(new JFormattedTextField()); 
    ftf = (JFormattedTextField) getComponent(); 
    minimum = new Double(min); 
    maximum = new Double(max); 

    //Set up the editor for the integer cells. 
    doubleFormat = new DecimalFormat("###.##");//Setting out the formatter here 
    doubleFormat.setMaximumFractionDigits(2);//2dp 
    NumberFormatter doubleFormatter = new NumberFormatter(doubleFormat); 
    doubleFormatter.setFormat(doubleFormat); 
    doubleFormatter.setMinimum(minimum); 
    doubleFormatter.setMaximum(maximum); 

    ftf.setFormatterFactory(
      new DefaultFormatterFactory(doubleFormatter)); 
    ftf.setValue(minimum); 
    ftf.setHorizontalAlignment(JTextField.CENTER); 
    ftf.setFocusLostBehavior(JFormattedTextField.PERSIST); 

    //React when the user presses Enter while the editor is 
    //active. (Tab is handled as specified by 
    //JFormattedTextField's focusLostBehavior property.) 
    ftf.getInputMap().put(KeyStroke.getKeyStroke(
      KeyEvent.VK_ENTER, 0), 
      "check"); 
    ftf.getActionMap().put("check", new AbstractAction() { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      if (!ftf.isEditValid()) { //The text is invalid. 
       if (userSaysRevert()) { //reverted 
        ftf.postActionEvent(); //inform the editor 
       } 
      } else { 
       try {    //The text is valid, 
        ftf.commitEdit();  //so use it. 
        ftf.postActionEvent(); //stop editing 
       } catch (java.text.ParseException exc) { 
       } 
      } 
     } 
    }); 
} 

//Override to invoke setValue on the formatted text field. 
@Override 
public Component getTableCellEditorComponent(JTable table, 
     Object value, boolean isSelected, 
     int row, int column) { 
    JFormattedTextField ftf 
      = (JFormattedTextField) super.getTableCellEditorComponent(
        table, value, isSelected, row, column); 
    ftf.setValue(value); 
    return ftf; 
} 

//Override to ensure that the value remains an Double. 
@Override 
public Object getCellEditorValue() { 
    JFormattedTextField ftf = (JFormattedTextField) getComponent(); 
    Object o = ftf.getValue(); 
    if (o instanceof Double) {//Watch out !!! 
     return o; 
    } else if (o instanceof Number) { 

     return new Double(((Number) o).doubleValue()); 
    } else { 
     if (DEBUG) { 
      System.out.println("getCellEditorValue: o isn't a Number"); 
     } 
     try { 
      return doubleFormat.parseObject(o.toString()); 
     } catch (ParseException exc) { 
      System.err.println("getCellEditorValue: can't parse o: " + o); 
      return null; 
     } 
    } 
} 

//Override to check whether the edit is valid, 
//setting the value if it is and complaining if 
//it isn't. If it's OK for the editor to go 
//away, we need to invoke the superclass's version 
//of this method so that everything gets cleaned up. 
@Override 
public boolean stopCellEditing() { 
    JFormattedTextField ftf = (JFormattedTextField) getComponent(); 
    if (ftf.isEditValid()) { 
     try { 
      ftf.commitEdit(); 
     } catch (java.text.ParseException exc) { 
     } 

    } else { //text is invalid 
     if (!userSaysRevert()) { //user wants to edit 
      return false; //don't let the editor go away 
     } 
    } 
    return super.stopCellEditing(); 
} 

/** 
* Lets the user know that the text they entered is bad. Returns true if the 
* user elects to revert to the last good value. Otherwise, returns false, 
* indicating that the user wants to continue editing. 
*/ 
protected boolean userSaysRevert() { 
    Toolkit.getDefaultToolkit().beep(); 
    ftf.selectAll(); 
    Object[] options = {"Edit", 
     "Revert"}; 
    int answer = JOptionPane.showOptionDialog(
      SwingUtilities.getWindowAncestor(ftf), 
      "The value must be an integer between " 
      + minimum + " and " 
      + maximum + ".\n" 
      + "You can either continue editing " 
      + "or revert to the last valid value.", 
      "Invalid Text Entered", 
      JOptionPane.YES_NO_OPTION, 
      JOptionPane.ERROR_MESSAGE, 
      null, 
      options, 
      options[1]); 

    if (answer == 1) { //Revert! 
     ftf.setValue(ftf.getValue()); 
     return true; 
    } 
    return false; 
} 
} 

這段代碼有什麼問題?

+2

在您的渲染器中使用合適的格式化程序,例如(https://stackoverflow.com/a/2511415/230513)。 – trashgod

+0

@trashgod它的工作,謝謝!我不知道我錯過了渲染。 – JWizard

回答

1

基於@ trashgod的評論,我能夠想出一個答案。我沒有現在我錯過了Table Cell Renderer,而是我專注於Editor。我瞭解到,這兩件事的工作方式不同,意味着不同的事情。根據Advice welcomed on creating my own Swing component回答。

我的自定義渲染器用於獲取雙值的列。

public class DoubleRenderer extends DefaultTableCellRenderer { 

DecimalFormat df; 

public DoubleRenderer(DecimalFormat df) { 
    this.df = df; 
    this.setHorizontalAlignment(JLabel.CENTER); 
    this.setBackground(Color.lightGray); 
    this.df.setParseBigDecimal(true); 
} 

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