Заставить ENTER работать с JSpinner так, как это происходит с JTextField
-
22-08-2019 - |
Вопрос
Во-первых, чтобы немного упростить мою работу по объяснению, вот некоторые из моего кода:
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;
}
}
Так что, как вы можете видеть, я зашел так далеко.И действительно, когда я ввожу значение в компонент текстового поля счетчика (JFormattedTextField
), а ЗАТЕМ нажмите ENTER, это работает.
Что я хочу сейчас, так это иметь возможность заставить текстовое поле реагировать на ВВОД без необходимости вручную вводить новое значение (что в некотором роде сводит на нет цель создания из него блесны).Как мне это сделать?
Решение
Я знаю, что это не action listener...но, может быть, это может сработать для вас?
text.addKeyListener( new KeyAdapter() {
@Override
public void keyReleased( final KeyEvent e ) {
if ( e.getKeyCode() == KeyEvent.VK_ENTER ) {
System.out.println( "enter pressed" );
}
}
} );
Другие советы
Я только что сам столкнулся с проблемой, связанной с этим.В моем случае у меня был JSpinner с SpinnerNumberModel
настройте так, чтобы я мог вводить числовые значения идентификаторов, а затем извлекать их из удаленной базы данных.Все это отлично работало с JButton в качестве триггера для запроса, но я хотел иметь возможность переключать фокус на поле с помощью Tab и нажимать enter, а также иметь возможность изменять значение, вводя идентификатор с помощью цифровых клавиш, затем нажимая enter.
Тот, который вызывал у меня больше всего проблем, заключался в ручном вводе идентификатора с помощью цифровых клавиш, а затем нажатии enter.Когда я делал это, запрос все равно выполнялся, но он запрашивал предыдущий идентификатор, а не тот, который я только что ввел, поэтому мне пришлось бы снова нажать 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
пока вы не нажмете enter, который также запускает прослушиватель ключей для запроса.В KeyEvent
для пользовательского [запроса] прослушиватель ключей, по-видимому, является первым в очереди, поэтому он сначала запускает свой код, а ЗАТЕМ KeyEvent
для применения значения к JSpinner
из внутреннего JFormattedTextField
, вот почему он запрашивает старое значение. SwingUtilities.invokeLater()
просто помещает сам запрос в конец очереди, чтобы он позволял другим KeyEvent
чтобы завершить его код перед запуском запроса.
Редактировать:
Другой способ добиться этого - запросить значение непосредственно у JFormattedTextField
вместо того , чтобы JSpinner
, поскольку это также должно возвращать вновь введенное значение , поскольку JFormattedTextField
содержит введенное вами значение, но оно еще не было передано JSpinner, в котором, по-видимому, и кроется проблема.
private void queryData() {
JFormattedTextField tf = ((JSpinner.DefaultEditor) minRng.getEditor()).getTextField();
int minVal = Integer.parseInt(tf.getText());
queryDataBase(minVal);
}
Единственная проблема с этим методом заключается в том, что затем вам придется перехватывать любые NumberFormatException
s, при разборе значения, где SwingUtilities.invokeLater()
подход позволяет модели spinner автоматически удалять все недопустимые символы и продолжать выполнение запроса.
В любом случае, я все еще несколько неопытен в Java, поэтому, если мое понимание этого неверно, пожалуйста, дайте мне знать в комментариях.