First, to make my job explaining a bit easier, here's some of my code:
JSpinner spin = new JSpinner();
JFormattedTextField text = getTextField(spin);
text.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
// Do stuff...
}
});
...
private JFormattedTextField getTextField(JSpinner spinner) {
JComponent editor = spinner.getEditor();
if (editor instanceof JSpinner.DefaultEditor) {
return ((JSpinner.DefaultEditor )editor).getTextField();
} else {
System.err.println( "Unexpected editor type: "
+ spinner.getEditor().getClass()
+ " isn't a descendant of DefaultEditor" );
return null;
}
}
So as you can see, I got that far. And indeed, when I type in a value into the text field component of the spinner (JFormattedTextField
), and THEN press ENTER, it works.
What I want now is to be able to have the text field respond to ENTER without having to manually type in a new value (which sorta defeats the purpose of making a spinner out of it). How do I do that?
I know this is not the action listener...but maybe this can work for you?
text.addKeyListener( new KeyAdapter() {
@Override
public void keyReleased( final KeyEvent e ) {
if ( e.getKeyCode() == KeyEvent.VK_ENTER ) {
System.out.println( "enter pressed" );
}
}
} );
I just ran into an issue relating to this, myself. In my case, I had a JSpinner with a SpinnerNumberModel
setup so I could input numerical ID values, and then retrieve them from a remote database. This worked all well and good with a JButton as my trigger for the query, but I wanted to be able to switch focus to the field via Tab, and hit enter, and also be able to change the value by entering an ID with numerical keys, then hit enter.
The one that was giving me the most issues was manually entering the ID with numerical keys, then pressing enter. When I would do this, the query would still happen, but it was querying the previous ID rather than the one I just entered, so I'd have to hit enter again to query the new ID (see code)
((JSpinner.DefaultEditor) minRng.getEditor()).getTextField().addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
queryData();
}
}
});
and the query method:
private void queryData() {
int minVal = Integer.parseInt(minRng.getValue().toString());
queryDataBase(minVal);
}
In order to fix this, all I had to do was force the query to wait to run until the spinner updated its value, which was easily done by using SwingUtilities.invokeLater()
to force it to the end of the EDT queue, like so:
((JSpinner.DefaultEditor) minRng.getEditor()).getTextField().addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
queryData();
}
});
}
}
});
Thanks to the invokeLater()
the query now happens on the new value rather than the previous one, when pressing enter, as the JSpinner has then updated its value to the newly input one.
I'm assuming the reason for this is that the value entered is not officially applied to the JSpinner
until you hit enter, which also fires the key listener for the query. The KeyEvent
for the custom [query] key listener appears to be the first one in the queue, so it runs its code first, and THEN the KeyEvent
for applying the value to the JSpinner
from the internal JFormattedTextField
, which is why it queries the old value. SwingUtilities.invokeLater()
just puts the query itself at the end of the queue, so it allows the other KeyEvent
to finish its code before running the query.
Edit:
Another way to achieve this is to request the value directly from the JFormattedTextField
rather than the JSpinner
, as this should also return the newly entered value since the JFormattedTextField
contains the value you typed in, but it hasn't yet been passed to the JSpinner, which appears to be where the issue lies.
private void queryData() {
JFormattedTextField tf = ((JSpinner.DefaultEditor) minRng.getEditor()).getTextField();
int minVal = Integer.parseInt(tf.getText());
queryDataBase(minVal);
}
The only problem with this method is that you then have to catch any NumberFormatException
s, when parsing the value, where the SwingUtilities.invokeLater()
approach allows the spinner model to remove any invalid characters, automatically, and continue with the query.
Anyway, I'm still somewhat inexperienced with Java, so if my understanding of this is incorrect, please let me know in the comments.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With