2014-01-16 50 views
3

對所有這個gr8 StackOverflow社區的問候。這是我嘗試自己解決它後的第一個問題,因此有點長... :-)
JSpinner在按下箭頭時沒有顯示最小值

我在使用向下箭頭鍵獲取最小指定值JSpinner時遇到問題。它接受如果在文本字段中鍵入的值。其他一切正常。奇怪的部分是,這隻發生在Spinner模型的某些組合中,具體爲new SpinnerNumberModel(29.6, 29.6, 118.1, 0.1)new SpinnerNumberModel(2.00, 2.00, 6.00, 0.01)。下面看到有這個問題的2 JSpinners的代碼。我不確定爲什麼這些模型會產生問題,以及是否有更多的模型存在這個問題。

import java.awt.EventQueue; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.Insets; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JSpinner; 
import javax.swing.SpinnerNumberModel; 

public class JSpinnerBug { 

    private JFrame frame; 
    private JSpinner spinner; 
    private JSpinner spinner_1; 
    private JButton btnChangeValue_1; 

    /** 
    * Launch the application. 
    */ 
    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       try { 
        JSpinnerBug window = new JSpinnerBug(); 
        window.frame.setVisible(true); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
    } 

    /** 
    * Create the application. 
    */ 
    public JSpinnerBug() { 
     initialize(); 
    } 

    /** 
    * Initialize the contents of the frame. 
    */ 
    private void initialize() { 
     frame = new JFrame(); 
     frame.setBounds(100, 100, 450, 300); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     GridBagLayout gridBagLayout = new GridBagLayout(); 
     gridBagLayout.columnWidths = new int[]{119, 88, 105, 0}; 
     gridBagLayout.rowHeights = new int[]{25, 0, 0}; 
     gridBagLayout.columnWeights = new double[]{0.0, 0.0, 0.0, Double.MIN_VALUE}; 
     gridBagLayout.rowWeights = new double[]{0.0, 0.0, Double.MIN_VALUE}; 
     frame.getContentPane().setLayout(gridBagLayout); 

     JButton btnChangeValue = new JButton("Change Value"); 
     btnChangeValue.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent arg0) { 
       spinner.setValue(2.00); 
      } 
     }); 

     spinner = new JSpinner(); 
     spinner.setModel(new SpinnerNumberModel(2.01, 2.00, 6.00, 0.01)); 
     GridBagConstraints gbc_spinner = new GridBagConstraints(); 
     gbc_spinner.fill = GridBagConstraints.HORIZONTAL; 
     gbc_spinner.insets = new Insets(0, 0, 5, 5); 
     gbc_spinner.gridx = 1; 
     gbc_spinner.gridy = 0; 
     frame.getContentPane().add(spinner, gbc_spinner); 
     GridBagConstraints gbc_btnChangeValue = new GridBagConstraints(); 
     gbc_btnChangeValue.insets = new Insets(0, 0, 5, 0); 
     gbc_btnChangeValue.anchor = GridBagConstraints.NORTHWEST; 
     gbc_btnChangeValue.gridx = 2; 
     gbc_btnChangeValue.gridy = 0; 
     frame.getContentPane().add(btnChangeValue, gbc_btnChangeValue); 

     spinner_1 = new JSpinner(); 
     spinner_1.setModel(new SpinnerNumberModel(29.7, 29.6, 118.1, 0.1)); 
     GridBagConstraints gbc_spinner_1 = new GridBagConstraints(); 
     gbc_spinner_1.fill = GridBagConstraints.HORIZONTAL; 
     gbc_spinner_1.insets = new Insets(0, 0, 0, 5); 
     gbc_spinner_1.gridx = 1; 
     gbc_spinner_1.gridy = 1; 
     frame.getContentPane().add(spinner_1, gbc_spinner_1); 

     btnChangeValue_1 = new JButton("Change Value"); 
     btnChangeValue_1.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       spinner_1.setValue(29.6); 
      } 
     }); 
     GridBagConstraints gbc_btnChangeValue_1 = new GridBagConstraints(); 
     gbc_btnChangeValue_1.gridx = 2; 
     gbc_btnChangeValue_1.gridy = 1; 
     frame.getContentPane().add(btnChangeValue_1, gbc_btnChangeValue_1); 
    } 

/** 
* Custom Spinner to detect button click on 
* JSpinner. This class fixes a bug for 
* JSpinner like for example for minimum value = 2.00 
* and step size 0.01 
* 
* @author dARKpRINCE 
* 
*/ 
class CustomSpinner extends JSpinner{ 

     @Override 
     public Object getPreviousValue() { 
      // Circumvent JSpinner bug 
      NumberEditor spinnerEditor = (NumberEditor) this.getEditor(); 
      SpinnerNumberModel model = spinnerEditor.getModel(); 
      if(model.getMinimum().equals(2.00) && model.getStepSize().equals(0.01)){ 
       if ((Double) getValue() == 2.01) { 
        return 2.00; 
       } 
       else { 
        return super.getPreviousValue(); 
       } 
      } 
      else if(model.getMinimum().equals(29.6) && model.getStepSize().equals(0.1)){ 
       if ((Double) getValue() == 29.7) { 
        return 29.6; 
       } 
       else { 
        return super.getPreviousValue(); 
       } 
      } 
      else { 
       return super.getPreviousValue(); 
      } 
     } 
    }  

} 

隨意嘗試其他型號,如new SpinnerNumberModel(55.3, 55.3, 118.1, 0.1)。隨着它的工作。

我的解決方案是擴展JSpinner(在代碼示例末尾給出),並關注每個創建此問題的模型,但這不是最優的。因此,每個JSpinner被替換爲CustomSpinner

我也檢查了JSpinner的源代碼,但無法確定/解決問題。任何人都可以告訴我,如果這是一個錯誤,並且如何最優地修復它?爲JSpinner使用第三方庫是我最後的選擇。

+0

爲了更好地幫助越早,張貼[MCVE(http://stackoverflow.com/help/mcve)。 –

+1

@Andrew Thompson:我真的不知道如何使它更緊湊。這個代碼示例只包含手頭的問題。 – dARKpRINCE

+0

C不代表'緊湊'。爲什麼不嘗試*閱讀(一個屏幕全文)文章,而不是隨機猜測? –

回答

2

BigDecimal#compareTo(...)Double#compareTo(...)出:

import java.awt.*; 
import java.math.*; 
import javax.swing.*; 
public class JSpinnerBug2 { 
    public static void main(String[] args) { 
    EventQueue.invokeLater(new Runnable() { 
     public void run() { 
     try { 
      JFrame frame = new JFrame(); 
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      frame.getContentPane().add(new JSpinnerBug2().makeUI()); 
      frame.setSize(320, 240); 
      frame.setLocationRelativeTo(null); 
      frame.setVisible(true); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     } 
    }); 
    } 
    public JComponent makeUI() { 
    Box box = Box.createVerticalBox(); 
    box.add(new JSpinner(new SpinnerNumberModel(2.01, 2.00, 6.00, 0.01))); 
    box.add(Box.createVerticalStrut(10)); 
    box.add(new JSpinner(new SpinnerNumberModel(29.7f, 29.6f, 111.8f, 0.1f))); 
    box.add(Box.createVerticalStrut(10)); 
    box.add(new JSeparator()); 

    //TEST: 
    double d = 29.7 - 29.6 - 0.1; 
    System.out.format("(%f-%f-%f>=0): %b%n", 29.7, 29.6, 0.1, d>=0); 
    System.out.format("(abs(%f-%f-%f)<1.0e-14): %b%n", 29.7, 29.6, 0.1, Math.abs(d)<1.0e-14); 
    System.out.format("(abs(%f-%f-%f)<1.0e-15): %b%n", 29.7, 29.6, 0.1, Math.abs(d)<1.0e-15); 

    box.add(new JSpinner(new SpinnerNumberModel(2.01f, 2.00f, 6.00f, 0.01f))); 
    box.add(Box.createVerticalStrut(10)); 
    box.add(new JSpinner(new SpinnerNumberModel(29.7, 29.6, 111.8, 0.1) { 
     @Override public Object getPreviousValue() { 
     Number v = getNumber(); 
     BigDecimal value = new BigDecimal(v.toString()); 
     BigDecimal stepSize = new BigDecimal(getStepSize().toString()); 
     BigDecimal maximum = new BigDecimal(getMaximum().toString()); 
     BigDecimal minimum = new BigDecimal(getMinimum().toString()); 
     BigDecimal newValue; 
     if (v instanceof Double) { 
      newValue = value.subtract(stepSize); 
     } else { 
      return super.getPreviousValue(); 
     } 
     if ((maximum != null) && (maximum.compareTo(newValue) < 0)) { 
      return null; 
     } 
     if ((minimum != null) && (minimum.compareTo(newValue) > 0)) { 
      return null; 
     } else { 
      return newValue; 
     } 
     } 
    })); 
    box.add(Box.createVerticalGlue()); 
    box.setBorder(BorderFactory.createEmptyBorder(20,20,20,20)); 
    return box; 
    } 
} 
+0

感謝您的解決方案。它完美的工作!我的問題是當我選擇重寫該方法對於所有型號還是僅選擇? – dARKpRINCE