java - 如何使 JFormattedTextField 在具有默认按钮的表单上正常运行?

标签 java swing jformattedtextfield

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

我还能够制定一个解决方法 - 如果您更改 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);
    }
}

所以问题是:有没有办法让 JFormattedTextField both 在 Enter 上提交(因此输入验证,但仅验证一次)<强>如果成功验证,激活默认按钮(按一下)?

最佳答案

基本技巧是让 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());

关于java - 如何使 JFormattedTextField 在具有默认按钮的表单上正常运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9101693/

相关文章:

java - 通过 Java 在 Chrome 中下载没有 .zip 扩展名的 Zip 文件

java - 连接 openfire 到 smack

java - 为什么我的 JScrollPane 不工作?

java - 如何将 ImageIcon 设置为 JButton 并根据按钮的大小调整图片大小?

java - 断言可迭代的每个元素都匹配给定匹配器的惯用 Hamcrest 模式是什么?

java - 在单个 Weblogic 域中的同一集群中部署两个 Spring 批处理应用程序?

Java Swing 不同高度组件的水平布局

java - 清除 JFormattedTextField 的内容不起作用?

java - 在Java中的TextField中仅引入数字形成间隔