Заставить ENTER работать с JSpinner так, как это происходит с JTextField

StackOverflow https://stackoverflow.com/questions/379675

Вопрос

Во-первых, чтобы немного упростить мою работу по объяснению, вот некоторые из моего кода:

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);
}

Единственная проблема с этим методом заключается в том, что затем вам придется перехватывать любые NumberFormatExceptions, при разборе значения, где SwingUtilities.invokeLater() подход позволяет модели spinner автоматически удалять все недопустимые символы и продолжать выполнение запроса.

В любом случае, я все еще несколько неопытен в Java, поэтому, если мое понимание этого неверно, пожалуйста, дайте мне знать в комментариях.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top