I have a JSpinner
inside a JTable
. When I edit the field manually by entering the numeric value by keyboard, the spinner does not take the value with the last digit entered. For example, if there was a 1 in the spinner and I enter a 2 in front (with which it would be 21) I only take 1, if then I enter a 3 in front (with which it would be a 321) I only take 21. All this action is processed in the keyPressed
event. This is the code for the entire class. By the way, if after entering the number, I press enter, I get all the digits well.
public class SpinnerEditor extends DefaultCellEditor
{
JSpinner spinner;
JSpinner.DefaultEditor editor;
JTextField textField;
boolean valueSet;
// Initializes the spinner.
public SpinnerEditor(DefaultTableModel modelo,JTable tabla) {
super(new JTextField());
spinner = new JSpinner();
editor = ((JSpinner.DefaultEditor)spinner.getEditor());
textField = editor.getTextField();
textField.addFocusListener( new FocusListener() {
public void focusGained( FocusEvent fe ) {
System.err.println("Got focus");
//textField.setSelectionStart(0);
//textField.setSelectionEnd(1);
SwingUtilities.invokeLater( new Runnable() {
public void run() {
if ( valueSet ) {
textField.setCaretPosition(1);
}
}
});
}
public void focusLost( FocusEvent fe ) {
}
});
textField.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent ae ) {
stopCellEditing();
}
});
spinner.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent e) {
try {
editor.commitEdit();
spinner.commitEdit();
} catch (ParseException ex) {
Logger.getLogger(SpinnerEditor.class.getName()).log(Level.SEVERE, null, ex);
}
if(tabla.getSelectedRow()>=0)
{
String precio = tabla.getValueAt(tabla.getSelectedRow(),2).toString();
int Iunidades = Integer.parseInt(spinner.getValue().toString());
double Dprecio=Double.parseDouble(precio);
double Total=Iunidades*Dprecio;
modelo.setValueAt(String.valueOf(Iunidades),tabla.getSelectedRow(), 7);
modelo.setValueAt(String.valueOf(Total),tabla.getSelectedRow(), 9);
}
}
});
((JSpinner.DefaultEditor)spinner.getEditor()).getTextField().addKeyListener(new KeyAdapter() {
//textField.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e)
{
char tecla=e.getKeyChar();
if(tecla>='0' && tecla<='9')
{
try {
editor.commitEdit();
spinner.commitEdit();
} catch (ParseException ex) {
Logger.getLogger(SpinnerEditor.class.getName()).log(Level.SEVERE, null, ex);
}
if(tabla.getSelectedRow()>=0)
{
String precio = tabla.getValueAt(tabla.getSelectedRow(),2).toString();
int Iunidades = Integer.parseInt(spinner.getValue().toString());
double Dprecio=Double.parseDouble(precio);
double Total=Iunidades*Dprecio;
modelo.setValueAt(String.valueOf(Iunidades),tabla.getSelectedRow(), 7);
modelo.setValueAt(String.valueOf(Total),tabla.getSelectedRow(), 9);
System.out.println(spinner.getValue().toString());
}
}
}
});
}
// Prepares the spinner component and returns it.
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column
) {
if ( !valueSet ) {
spinner.setValue(value);
}
SwingUtilities.invokeLater( new Runnable() {
public void run() {
textField.requestFocus();
}
});
return spinner;
}
public boolean isCellEditable( EventObject eo ) {
System.err.println("isCellEditable");
if ( eo instanceof KeyEvent ) {
KeyEvent ke = (KeyEvent)eo;
System.err.println("key event: " ke.getKeyChar());
textField.setText(String.valueOf(ke.getKeyChar()));
//textField.select(1,1);
//textField.setCaretPosition(1);
//textField.moveCaretPosition(1);
valueSet = true;
} else {
valueSet = false;
}
return true;
}
// Returns the spinners current value.
public Object getCellEditorValue() {
return spinner.getValue();
}
public boolean stopCellEditing() {
System.err.println("Stopping edit");
try {
editor.commitEdit();
spinner.commitEdit();
} catch ( java.text.ParseException e ) {
JOptionPane.showMessageDialog(null,
"Invalid value, discarding.");
}
return super.stopCellEditing();
}
}
CodePudding user response:
. All this action is processed in the keyPressed event.
Which is the issue.
Instead you should be handling the keyTyped
event.
Or better yet you should be using a DocumentListener
. A `DocumentListener will work even if text is pasted into the text field. You should always design your GUI so that it will work with the keyboard and the mouse.
Read the section from the Swing tutorial on How to Write a DocumentListener for more information and examples.
CodePudding user response:
If you just want a spinner that only accepts int values, and acts as a table cell editor, you don’t need all that custom handling:
public class SpinnerEditor
extends AbstractCellEditor
implements TableCellEditor {
private static final long serialVersionUID = 1;
private final JSpinner spinner;
public SpinnerEditor() {
spinner = new JSpinner(
new SpinnerNumberModel(1, 0, Integer.MAX_VALUE, 1));
}
@Override
public Component getTableCellEditorComponent(JTable table,
Object value,
boolean selected,
int row,
int column) {
spinner.setValue(value);
return spinner;
}
@Override
public Object getCellEditorValue() {
return spinner.getValue();
}
}