3

我想在按 ENTER 键时进行一些输入验证JDateChooser。我知道在JTextField元素中可以添加一个ActionListenerENTER 键触发一个动作。但是,当我ActionListener在日期选择器中添加并按 ENTER 时,并不总是会收到该操作。

在下面的示例中,当程序第一次启动时按 ENTER 键会在 中触发一个动作,JDateChooser并且焦点会按预期遍历到下一个组件。但是,在随后的遍历中,我必须在触发动作之前输入一个字符。JTextField正如预期的那样,在这两个元素中触发了一个动作。

谁能解释为什么在将 a 添加ActionListener到 a 的编辑器时 ENTER 键的行为并不总是相同JDateChooser

带有一个 JDateChooser 和两个 JTextField 元素的 JFrame

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import com.toedter.calendar.JDateChooser;

public class DateExample extends JFrame implements ActionListener {
    private static final long serialVersionUID = 1L;
    private JPanel contentPane;
    private JTextField textField;
    private JTextField textField_1;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    DateExample frame = new DateExample();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public DateExample() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(new GridLayout(0, 1, 0, 0));

        JDateChooser dateChooser = new JDateChooser("yyyy/MM/dd", "####/##/##", '_');
        ((JTextField) dateChooser.getDateEditor().getUiComponent()).addActionListener(this);
        contentPane.add(dateChooser);

        textField = new JTextField();
        textField.setColumns(10);
        textField.addActionListener(this);
        contentPane.add(textField);

        textField_1 = new JTextField();
        textField_1.setColumns(10);
        textField_1.addActionListener(this);
        contentPane.add(textField_1);

        pack();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Action received.");
        KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent();
    }

}
4

2 回答 2

0

谁能解释为什么在将 a 添加ActionListener到 a 的编辑器时 ENTER 键的行为并不总是相同JDateChooser

碰巧附加到JDateChooser组件的IDateEditor接口的默认实现的 UI 组件不是普通的JTextField,而是实际上是JFormattedTextField。当格式化文本字段具有焦点并且您按 ENTER 键时,插入文本字段中的文本将发送到底层格式化程序以验证它并更新模型。通过附加或设置通过键绑定机制,我们可能会干扰此默认行为,结果是不可预测的。ActionListenerAction

我强烈建议你不要这样做,让格式化的文本字段做它应该做的事情。

注意:接口的默认实现IDateEditor称为 JTextFieldDateEditor,其代码可在此处获得

我想在按 ENTER 键时进行一些输入验证JDateChooser

在这种情况下,我建议您遵循“预防性”方法,尽可能限制用户输入以避免他们引入不正确的值,而不是在输入发生验证输入。为此,我们可以使用一些有用的工具:

  • JDateChooser通过API设置最小/最大可选日期。

  • 附加实现IDateEvaluator接口的日期评估器。这对于使一个或多个日期无效以防止用户选择它们很有用。请参阅此处此处的示例。

  • 实现我们自己的IDateEditor. 我们可以将默认实现作为基础并使用格式化程序。注意:我会避免扩展JFormattedTextField并改用组合。在这个问题中有一个早期的实施尝试(尽管需要完善)。

于 2014-11-11T15:52:46.263 回答
0

为了验证,您可以将 caretListener 添加到编辑器,或者您可以扩展 JDateChooser 并覆盖 propertyChange 方法。

根据个人经验,我最终创建了自己的 TextFieldDateEditor

public class MyDateEditor implements com.toedter.calendar.IDateEditor

并用

public JDateChooser(Date date, String dateFormatString, IDateEditor dateEditor)

这样您就可以根据需要与文本字段进行交互。

于 2014-11-11T11:00:53.583 回答