propiedades limitar fecha java swing event-handling jspinner changelistener

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.