3

I would like to do some input validation when the ENTER key is pressed in a JDateChooser. I know that in JTextField elements it is possible to add an ActionListener whereby the ENTER key fires an action. However, when I add an ActionListener and press ENTER in the date chooser, the action is not always received.

In the below example, pressing the ENTER key when the program first starts fires an action in the JDateChooser and the focus traverses to the next component as expected. However, in subsequent traversals, I have to enter a character before an action is fired. An action is fired in the two JTextField elements as expected.

Can anyone explain why the ENTER key does not always behave the same when adding an ActionListener to the editor of a JDateChooser?

JFrame with a JDateChooser and two JTextField elements

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

}
David Yee
  • 3,515
  • 25
  • 45
  • Why don't you try `keyPressed` Action event with JDateChooser? – Am_I_Helpful Jun 20 '14 at 08:53
  • 1
    depends of is is there used JComboBox or JSpinner as editor, you have to create [own list of accesible JComponents](http://stackoverflow.com/a/11203873/714968), set, moving with focus by using KeyBindings, note there could be important to set focus to the proper container, I'd be use code source, add/modify/override desired methods, note this calendar has excelent workaround for focus for its popup window (the best as I know), don't kill that :-) – mKorbel Jun 20 '14 at 08:53
  • @shekharsuman Yes, a `KeyListener` does work but are there disadvantages of using it over an `ActionListener`? I have read many recommendations against using a `KeyListener` for handling the ENTER key. – David Yee Jun 20 '14 at 09:46
  • @mKorbel The editor actually seems to be a `JTextField` (see image) although it does use a `JComboBox` and `JSpinner` in its pop-up calendar. Thanks for the tip about `KeyBindings`! – David Yee Jun 20 '14 at 09:56

2 Answers2

0

for validating you can add a caretListener to the editor or you can extend JDateChooser and overwrite the propertyChange method.

on personal experience, i ended up creating my own TextFieldDateEditor

public class MyDateEditor implements com.toedter.calendar.IDateEditor

and called it with

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

that way you can interact with the textfield as you like.

gantners
  • 471
  • 4
  • 16
0

Can anyone explain why the ENTER key does not always behave the same when adding an ActionListener to the editor of a JDateChooser?

It happens that the UI component of the default implementation of IDateEditor interface attached to JDateChooser component is not a plain JTextField but actually a JFormattedTextField. When a formatted text field has focus and you press ENTER key, the text inserted in the text field is sent to the underlying formatter in order to validate it and update the model. By attaching an ActionListener or by setting an Action through Key Binding mechanism we might interfer with this default behavior and the result is unpredictable.

I'd strongly suggest you don't do that and let the formatted textfield do what it is supposed to do.

Note: the default implementation of IDateEditor interface is called JTextFieldDateEditor and its code is available here

I would like to do some input validation when the ENTER key is pressed in a JDateChooser.

In this case I'd suggest you follow a "preventive" approach by limiting users input as much as possible to avoid them introduce incorrect values, instead of validating the input after it happened. There are some useful tools we can use for this purpose:

  • Set minimum/maximum selectable dates through JDateChooser API.

  • Attach date evaluators that implements IDateEvaluator interface. This is useful to invalidate one or more dates preventing users can select them. See examples here or here.

  • Implement our own IDateEditor. We can take the default implementation as base and play with formatters. Note: I'd avoid extending JFormattedTextField and use composition instead. There is an early attempt of implementation shwon in this question (needs to be polished, though).

Community
  • 1
  • 1
dic19
  • 17,821
  • 6
  • 40
  • 69