Discussion:
JSpinner input validation, numbers
(too old to reply)
Daniel
2005-10-18 00:18:33 UTC
Permalink
Hi,
I have a rather large number of spinners in my application. Their
values vary but often ranges from 1 to 99. So I want the user to be
able to type in the number if they want to make a big change.
Now as we know, users never do what you intend them to do. So at
present if the user types in 9000, nothing happens until the spinner
looses focus and then it changes to the previous value. I would like
at that moment display a dialogbox or similar to inform the user that
the value they sat was invalid, and that it has been restored.

How do I go about this in the simplest way?
I already "subscribe" to the statechanges, but they are only fired
when a legal value is entered.
Basically all I want is notification that the spinner has rejected the
typed value. Is that possible?

regards
Daniel
Roedy Green
2005-10-18 06:19:05 UTC
Permalink
On Tue, 18 Oct 2005 00:18:33 GMT, Daniel
Post by Daniel
How do I go about this in the simplest way?
How about implementing a ChangeListener that gets invoked if anything
so much as breathes. In that code, you check consistency and corral
values back to reasonable.

If that does not work, use a listener on keystrokes too.
--
Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.
Daniel
2005-10-18 07:09:31 UTC
Permalink
Post by Roedy Green
Post by Daniel
How do I go about this in the simplest way?
How about implementing a ChangeListener that gets invoked if anything
so much as breathes. In that code, you check consistency and corral
values back to reasonable.
If that does not work, use a listener on keystrokes too.
Sorry, I was using the ChangeListener, so with that I do not get a
change unless the spinner loses focus, and of course the value is
changed. So with an invalid value, I do not get a change.
So I guess I will have to use a key Listener.

thanks anyway
daniel
Michael Dunn
2005-10-19 03:47:40 UTC
Permalink
I don't like editable spinners, for the reasons you've described.

Perhaps you may be able to roll-your-own, something like this
note: this is quick'n'dirty - display purposes only
(needs 'spinner' mouse action)

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.plaf.basic.BasicSpinnerUI;
class Testing extends JFrame
{
final int MIN = 0;
final int MAX = 10000;
final int STEP = 1;
JTextField tf;
public Testing()
{
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocation(400,300);
JSpinner spinner = new JSpinner();
spinner.setUI(new MyUI());
tf = new JTextField(new SpinnerLimiter(),"0",10){public void
paste(){}};
tf.setHorizontalAlignment(JTextField.RIGHT);
spinner.setEditor(tf);
JPanel jp = new JPanel();
jp.add(spinner);
getContentPane().add(jp,BorderLayout.CENTER);
getContentPane().add(new JTextField("to take
focus"),BorderLayout.SOUTH);
pack();
}
public void changeValue(int amount)
{
String currentText = tf.getText();
if(currentText.equals("")) currentText = "0";
int oldNumber = Integer.parseInt(currentText);
if((oldNumber == MIN && amount < 0)|| (oldNumber == MAX && amount >
0)) return;
tf.setText(String.valueOf(oldNumber+amount));
}
class SpinnerLimiter extends PlainDocument
{
String preErrorText = "0";
public void insertString(int offs, String str, AttributeSet a)
throws BadLocationException
{
String oldText = getText(0,getLength());
if(oldText.equals("")) oldText = preErrorText;
try{int testValid = Integer.parseInt(str);}
catch(NumberFormatException nfe)
{
java.awt.Toolkit.getDefaultToolkit().beep();
return;
}
super.insertString(offs, str, a);
String newText = getText(0,getLength());
int number = Integer.parseInt(newText);
if(number < MIN || number > MAX)
{
tf.setText(preErrorText);
java.awt.Toolkit.getDefaultToolkit().beep();
return;
}
preErrorText = newText;
}
}
class MyUI extends BasicSpinnerUI
{
protected Component createNextButton()
{
JButton btnNext = (JButton)super.createNextButton();
btnNext.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae){
changeValue(STEP);}});
return btnNext;
}
protected Component createPreviousButton()
{
JButton btnPrevious = (JButton)super.createPreviousButton();
btnPrevious.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae){
changeValue(-STEP);}});
return btnPrevious;
}
}
public static void main(String[] args){new
Testing().setVisible(true);}
}

Loading...