limitar - propiedades jspinner java
JSpinner Value change Eventos (6)
El código que muestra parece correcto. Como referencia, aquí hay un ejemplo de trabajo.
Adición: Mientras que el JSpinner
tiene foco, las teclas de flecha izquierda y derecha mueven el cursor. La flecha hacia arriba se incrementa y la flecha hacia abajo disminuye el campo que contiene el cursor. El cambio es (efectivamente) simultáneo tanto en la ruleta como en la etiqueta.
Para acceder al JFormattedTextField
del JSpinner.DateEditor
, use el método getTextField()
los padres. Luego, se puede usar un oyente de intercalación apropiado o un oyente de entrada de texto para actualizar la etiqueta como se desee.
Adición: Actualice para usar setCommitsOnValidEdit
, como se sugiere here .
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.util.Calendar;
import java.util.Date;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JSpinner.DateEditor;
import javax.swing.SpinnerDateModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.DefaultFormatter;
/**
* @see https://stackoverflow.com/questions/2010819
* @see https://stackoverflow.com/questions/3949518
*/
public class JSpinnerTest extends JPanel {
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame f = new JFrame("JSpinnerTest");
f.add(new JSpinnerTest());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
});
}
public JSpinnerTest() {
super(new GridLayout(0, 1));
final JLabel label = new JLabel();
final JSpinner spinner = new JSpinner();
Calendar calendar = Calendar.getInstance();
Date initDate = calendar.getTime();
calendar.add(Calendar.YEAR, -5);
Date earliestDate = calendar.getTime();
calendar.add(Calendar.YEAR, 10);
Date latestDate = calendar.getTime();
spinner.setModel(new SpinnerDateModel(
initDate, earliestDate, latestDate, Calendar.MONTH));
DateEditor editor = new JSpinner.DateEditor(spinner, "MMM yyyy");
spinner.setEditor(editor);
JFormattedTextField jtf = editor.getTextField();
DefaultFormatter formatter = (DefaultFormatter) jtf.getFormatter();
formatter.setCommitsOnValidEdit(true);
spinner.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
JSpinner s = (JSpinner) e.getSource();
label.setText(s.getValue().toString());
}
});
label.setText(initDate.toString());
this.add(spinner);
this.add(label);
}
}
Cómo hacer la actualización inmediatamente cuando se cambió el valor de jSpinner.
ChangeListener listener = new ChangeListener() {
public void stateChanged(ChangeEvent e) {
jLabel.setText(e.getSource());
}
};
spinner1.addChangeListener(listener);
El código anterior no cambia automáticamente el texto de la etiqueta, requiere que haga clic de nuevo en cualquier lugar para actualizar.
El problema aquí es que cuando edita el valor de JSpinner
manualmente escribiendo desde el teclado, el evento stateChanged
no se JSpinner
hasta que el JSpinner
pierde el JSpinner
o hasta que se presiona la tecla Enter.
Si desea cargar el valor, se necesita un KeyListener
que realice un setValue
en el JSpinner
para cada clave escrita.
Dejo aquí un ejemplo para un JSpinner
con un SpinnerNumberModel
:
JSpinner spinner= new JSpinner();
spinner.setModel(new SpinnerNumberModel(0, 0, Integer.MAX_VALUE, 1));
spinner.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
jLabel.setText(spinner.getValue());
}
});
final JTextField jtf = ((JSpinner.DefaultEditor) spinner.getEditor()).getTextField();
jtf.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
String text = jtf.getText().replace(",", "");
int oldCaretPos = jtf.getCaretPosition();
try {
Integer newValue = Integer.valueOf(text);
spinner.setValue(newValue);
jtf.setCaretPosition(oldCaretPos);
} catch(NumberFormatException ex) {
//Not a number in text field -> do nothing
}
}
});
La última respuesta se puede reorganizar un poco para hacerlo un poco más flexible. Simplemente puede usar este nuevo MyJSpinner en lugar de cualquier JSpinner. El mayor cambio es que puede usar esta nueva versión con cualquier modelo subyacente de JSpinner (int, double, byte, etc.)
public class MyJSpinner extends JSpinner{
boolean setvalueinprogress=false;
public MyJSpinner()
{
super();
final JTextField jtf = ((JSpinner.DefaultEditor) getEditor()).getTextField();
jtf.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
showChangedValue(e);
}
@Override
public void insertUpdate(DocumentEvent e) {
showChangedValue(e);
}
@Override
public void changedUpdate(DocumentEvent e) {
showChangedValue(e);
}
private void showChangedValue(DocumentEvent e){
try {
if (!setvalueinprogress)
MyJSpinner.this.commitEdit();
} catch (NumberFormatException | ParseException ex) {
//handle if you want
Exceptions.printStackTrace(ex);
}
}
});
}
@Override
public void setValue(Object value) {
setvalueinprogress=true;
super.setValue(value);
setvalueinprogress=false;
}
}
La respuesta es configurar el formateador utilizado en JFormattedTextField, que es un elemento secundario del editor del spinner:
formatter.setCommitsOnValidEdit(true);
Desafortunadamente, ponerle la mano es tan largo y sucio como la frase introductoria:
final JSpinner spinner = new JSpinner();
JComponent comp = spinner.getEditor();
JFormattedTextField field = (JFormattedTextField) comp.getComponent(0);
DefaultFormatter formatter = (DefaultFormatter) field.getFormatter();
formatter.setCommitsOnValidEdit(true);
spinner.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
LOG.info("value changed: " + spinner.getValue());
}
});
Una manera leve (aunque no demasiado) más limpia podría ser subclasificar NumberEditor y exponer un método que permita la configuración
Puede ser una respuesta tardía, pero puede usar mi enfoque.
Como spuas mencionadas anteriormente, el problema es que el evento stateChanged
se stateChanged
solo cuando se pierde el foco o se presiona la tecla Enter.
Usar KeyListeners tampoco es una buena idea.
Sería mejor usar DocumentListener
lugar. Modifiqué un poco el ejemplo de spuas y eso es lo que obtuve:
JSpinner spinner= new JSpinner();
spinner.setModel(new SpinnerNumberModel(0, 0, Integer.MAX_VALUE, 1));
final JTextField jtf = ((JSpinner.DefaultEditor) spinner.getEditor()).getTextField();
jtf.getDocument().addDocumentListener(new DocumentListener() {
private volatile int value = 0;
@Override
public void removeUpdate(DocumentEvent e) {
showChangedValue(e);
}
@Override
public void insertUpdate(DocumentEvent e) {
showChangedValue(e);
}
@Override
public void changedUpdate(DocumentEvent e) {
showChangedValue(e);
}
private void showChangedValue(DocumentEvent e){
try {
String text = e.getDocument().getText(0, e.getDocument().getLength());
if (text==null || text.isEmpty()) return;
int val = Integer.parseInt(text).getValue();
if (value!=val){
System.out.println(String.format("changed value: %d",val));
value = val;
}
} catch (BadLocationException | NumberFormatException e1) {
//handle if you want
}
}
});
Soy nuevo, así que podría romper algunas reglas y podría llegar tarde. Pero encontré algunas de las respuestas un poco confusas, así que jugué en NetBeans IDE y descubrí que si hace clic derecho en el componente jspinner GUI colocado en su jform y va a eventos-> cambiar, se generará código para usted.