Я сам столкнулся с проблемой, связанной с этим. В моем случае у меня был JSpinner с настройкой SpinnerNumberModel
, чтобы я мог вводить числовые значения идентификаторов, а затем извлекать их из удаленной базы данных. Это хорошо работало с JButton в качестве моего триггера для запроса, но я хотел иметь возможность переключать фокус на поле через Tab и нажимать клавишу ввода, а также иметь возможность изменять значение, вводя идентификатор с помощью цифровых клавиш , затем нажмите Enter.
Единственное, что доставляло мне больше всего проблем, - это ввод вручную идентификатора с помощью цифровых клавиш и затем нажатие клавиши ввода. Когда я делал это, запрос все равно выполнялся, но он запрашивал предыдущий идентификатор, а не тот, который я только что ввел, поэтому мне пришлось бы снова нажать клавишу ввода, чтобы запросить новый идентификатор (см. Код)
((JSpinner.DefaultEditor) minRng.getEditor()).getTextField().addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
queryData();
}
}
});
и метод запроса:
private void queryData() {
int minVal = Integer.parseInt(minRng.getValue().toString());
queryDataBase(minVal);
}
Чтобы исправить это, все, что мне нужно было сделать, это заставить запрос ждать, пока он не обновит свое значение, что было легко сделать с помощью SwingUtilities.invokeLater()
, чтобы принудительно завершить его в конец очереди EDT, как так:
((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();
}
});
}
}
});
Благодаря invokeLater()
запрос теперь выполняется по новому значению, а не по предыдущему, при нажатии enter, поскольку JSpinner затем обновил свое значение до вновь введенного.
Я предполагаю, что причина этого в том, что введенное значение официально не применяется к JSpinner
до тех пор, пока вы не нажмете клавишу ввода, что также запускает прослушиватель ключей для запроса. KeyEvent
для пользовательского прослушивателя ключа [query] является первым в очереди, поэтому он сначала запускает свой код, а затем KeyEvent
для применения значения к JSpinner
из внутреннего JFormattedTextField
Вот почему он запрашивает старое значение. SwingUtilities.invokeLater()
просто помещает сам запрос в конец очереди, поэтому он позволяет другому KeyEvent
завершить код перед выполнением запроса.
Edit:
Другой способ добиться этого - запросить значение непосредственно у JFormattedTextField
, а не JSpinner
, поскольку это также должно вернуть вновь введенное значение, поскольку JFormattedTextField
содержит введенное вами значение, но оно не имеет еще не были переданы JSpinner, который, как представляется, в чем проблема.
private void queryData() {
JFormattedTextField tf = ((JSpinner.DefaultEditor) minRng.getEditor()).getTextField();
int minVal = Integer.parseInt(tf.getText());
queryDataBase(minVal);
}
Единственная проблема с этим методом заключается в том, что вам нужно перехватить любые NumberFormatException
с при анализе значения, когда подход SwingUtilities.invokeLater()
позволяет моделируемой спиннеру автоматически удалять любые недопустимые символы и продолжать выполнение запроса. .
В любом случае, я все еще немного неопытен в Java, поэтому, если я не понимаю этого, пожалуйста, дайте мне знать в комментариях.