Как заставить JFormattedTextField вести себя правильно на форме с кнопкой по умолчанию? - PullRequest
1 голос
/ 01 февраля 2012

Я сталкиваюсь с проблемой, используя кнопку формы по умолчанию, когда она (форма) включает JFormattedTextField.Если в форме с таким полем есть фокус (и он был изменен), необходимо нажать кнопку OK дважды , чтобы нажать кнопку по умолчанию.Я думаю, я знаю, почему это происходит - это потому, что первый Enter используется при обработке коммитов.

Я также смог сделать обходной путь - если вы измените Formatter для фиксации при каждом действительном редактировании, то вы получите правильное поведение, но это а) заставит вас указать эксплицит форматеров, и б) этоневозможно вернуться к «старому» значению (например, с помощью Escape или программно).

Код ниже демонстрирует, что: когда вы запускаете его, поле вверху фиксирует каждое редактирование и работает с одним Enter (но вы не можете отменить), поле внизу допускает возврат, но требует two Входит, если отредактировано.

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.text.DateFormatter;

public class ExFrame extends JFrame {

    private JPanel contentPane;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    ExFrame frame = new ExFrame();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    /**
     * Create the frame.
     */
    public ExFrame() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(contentPane);

        JFormattedTextField ff_1, ff_2;

        //ff_1 has modified behavior of commit on each (valid) edit
        DateFormatter f=new DateFormatter();
        f.setCommitsOnValidEdit(true);

        ff_1 = new JFormattedTextField(f);
        ff_1.setValue(new Date());

        //ff_2 has default behavior 
        ff_2 = new JFormattedTextField(new Date());

        contentPane.add(ff_1, BorderLayout.NORTH);
        contentPane.add(ff_2, BorderLayout.SOUTH);

        JButton btnDefault = new JButton("I am default button");
        contentPane.add(btnDefault, BorderLayout.CENTER);
        getRootPane().setDefaultButton(btnDefault);
    }
}

Так что вопрос: есть ли способ получить JFormattedTextField оба коммит при Enter (так что ввод проверен проверен, нотолько один раз) и, если успешно подтверждено , активировать кнопку по умолчанию (одним нажатием)?

Ответы [ 4 ]

2 голосов
/ 15 августа 2012

Основная хитрость заключается в том, чтобы обмануть механизм связывания ключей, полагая, что keyStroke не был обработан textField.Чтобы достичь этого, нам нужно создать подкласс JFormattedTextField и переопределить его processKeyBindings для возврата false (что означает: «невозможно использовать»).

Что-то вроде:

JFormattedTextField multiplex = new JFormattedTextField() {
    KeyStroke enter = KeyStroke.getKeyStroke("ENTER");
    @Override
    protected boolean processKeyBinding(KeyStroke ks, KeyEvent e,
                                        int condition, boolean pressed) {
        boolean processed = super.processKeyBinding(ks, e, condition,
                                                    pressed);

        if (processed && condition != JComponent.WHEN_IN_FOCUSED_WINDOW
                && enter.equals(ks)) {
            // Returning false will allow further processing
            // of the bindings, eg our parent Containers will get a
            // crack at them and f.i. route to a default button.
            return !isEditValid();
        }
        return processed;
    }

};
multiplex.setValue(new Date());
1 голос
/ 01 февраля 2012

для экземпляра Date / Number (в большинстве случаев) лучше использовать JSpinner вместо JFormattedTextField , тогда вы можете установить только для DateSpinnerModel с помощью Locale или SimpleDateFormat,

и для JSpinner с Number Экземпляром (действительно для JTextField) необходимо добавить Документ для удаления / фильтрации нежелательных символов

0 голосов
/ 12 ноября 2012

Ни один из ваших ответов не решил мою проблему с приложением.Однако в моем случае решение проблемы оказалось намного проще:

private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {
   add(jTextField1);          //this reacts after the "ENTER" gets pressed
   jButton1.doClick();        //this activates the button with Enter
   jTextField1.setText("");   //this removes the text from a text-field
  jTextField1.grabFocus();    //this sets a cursor within a text-field

//Whenever the Enter is pressed, after the typed text, the action is performed again.
    }
0 голосов
/ 15 августа 2012

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

ff_1.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), new Object());
ff_2.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), new Object());

пока и будь клевым;)

...