2

当它(表单)包含JFormattedTextField. 在具有此类字段的表单上,如果它恰好具有焦点(并且已更改),则必须按两次确定才能“按下”默认按钮。我想我知道它为什么会发生 - 这是因为第一个 Enter 在 Commit 处理中被消耗掉了。

我还能够提出一种解决方法 - 如果您更改Formatter为在每次有效编辑时提交,那么您将获得正确的行为,但这 a) 会强制您指定格式化程序,并且 b) 无法恢复为“旧”值(例如,使用 Escape 或以编程方式)。

下面的代码演示了:当您在每次编辑时运行顶部提交的字段并使用单个 Enter(但您无法还原)时,底部的字段允许还原,但如果编辑则需要两个Enter。

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

所以问题是:有没有办法在 Enter 上JFormattedTextField 同时提交(所以输入验证但只验证一次),如果成功验证,激活默认按钮(只需按一下)?

4

4 回答 4

2

基本技巧是让 keyBinding 机制傻到相信 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());
于 2012-08-15T09:56:25.473 回答
1

对于 Date / Number 实例(在大多数情况下)更好地使用JSpinner而不是JFormattedTextField,那么您只能使用or设置DateSpinnerModelLocaleSimpleDateFormat

对于Instance (对 有效JSpinner),您必须添加Document 以删除/过滤不需要的字符NumberJTextField

于 2012-02-01T19:19:39.587 回答
0

您的两个答案都没有解决我的应用程序问题。但是,在我的情况下,问题解决方案似乎要简单得多:

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.
    }
于 2012-11-12T16:33:38.037 回答
0

Enter 通常用于接受当前值,因此 JFTF 中的 enter 也执行此操作。您可以通过执行以下操作禁用它:

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

再见,冷静点;)

于 2012-08-15T08:31:43.230 回答