Greetings to all of this gr8 StackOverflow community. This is my first question after trying to solve it myself and thus is kinda long... :-)
I'm having problem with getting the minimum specified value of JSpinner
using the down arrow key. It accepts the value if typed in the text field. Everything else works fine. The strange part of this is, that this occurs in only some combination of Spinner models, specifically new SpinnerNumberModel(29.6, 29.6, 118.1, 0.1)
and new SpinnerNumberModel(2.00, 2.00, 6.00, 0.01)
. Below see the code of 2 JSpinners
that have this problem. I'm not sure why these models create the problems and if there are more models that have this problem.
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();
}
}
}
}
Feel free to try with other models like new SpinnerNumberModel(55.3, 55.3, 118.1, 0.1)
. With that it works.
My solution was to extend the JSpinner (given at the end of the code example) and attend to each model that creates this problem, which is not optimal. Thus each JSpinner
was replaced by CustomSpinner
.
I also checked the source code of JSpinner but was not able to determine/fix the problem. Can anyone tell me if this is a bug and how to optimally fix it? Using a third-party library for JSpinner would be my last resort.