javaswingjdatechooserfocuslistener

JDateChooser focusListener


I'm trying to add a focusListener to JDateChooser, so that when the user chooses the dateOfBirth it displays age on the textfield when the focus is lost. But it is not working This is the way i've tried,

import java.awt.BorderLayout;

public class agecalc extends JFrame {
    private JTextField age;
    private JDateChooser dOB;
    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    agecalc frame = new agecalc();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public agecalc() {

        JPanel panel = new JPanel();
        GroupLayout groupLayout = new GroupLayout(getContentPane());
        groupLayout.setHorizontalGroup(
            groupLayout.createParallelGroup(Alignment.LEADING)
                .addGroup(groupLayout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(panel, GroupLayout.PREFERRED_SIZE, 290, GroupLayout.PREFERRED_SIZE)
                    .addContainerGap(134, Short.MAX_VALUE))
        );
        groupLayout.setVerticalGroup(
            groupLayout.createParallelGroup(Alignment.LEADING)
                .addGroup(groupLayout.createSequentialGroup()
                    .addGap(20)
                    .addComponent(panel, GroupLayout.PREFERRED_SIZE, 195, GroupLayout.PREFERRED_SIZE)
                    .addContainerGap(47, Short.MAX_VALUE))
        );
        panel.setLayout(null);

        dOB = new JDateChooser();
        dOB.setBounds(97, 52, 95, 20);
        panel.add(dOB);

        age = new JTextField();
        age.setBounds(97, 83, 86, 20);
        panel.add(age);
        age.setColumns(10);
        getContentPane().setLayout(groupLayout);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);

                    AGECalc ageCalc=new AGECalc();

        dOB.addFocusListener(ageCalc);
    }
    private class AGECalc implements FocusListener{

        @Override
        public void focusGained(FocusEvent e) {         

        }

        @Override
        public void focusLost(FocusEvent e) {
            // TODO Auto-generated method stub
            Calendar fromDate;
               Calendar toDate;
               Date dateOfBirth= dOB.getDate();
               Date now = new Date();
               fromDate=Calendar.getInstance();
               toDate=Calendar.getInstance();

                   fromDate.setTime(dateOfBirth);
                   toDate.setTime(now);
                   int ageYear = toDate.get(Calendar.YEAR) - (fromDate.get(Calendar.YEAR) );
                   age.setText(Integer.toString(ageYear));
                   System.out.println(ageYear);   



            }
        }






    public JTextField getAge() {
        return age;
    }

    public void setAge(JTextField age) {
        this.age = age;
    }

    public JDateChooser getdOB() {
        return dOB;
    }

    public void setdOB(JDateChooser dOB) {
        this.dOB = dOB;
    }
}

Solution

  • I'm trying to add a focusListener to JDateChooser, so that when the user chooses the dateOfBirth it displays age on the textfield when the focus is lost.

    Instead of that I'd suggest you to implement a PropertyChangeListener and attach it to the date chooser. In this way the text field will be updated every time the user updates the selected value by picking a date or by input a new date manually, regardless the date chooser loses the focus or not.

    For instance:

    final JTextField ageTextField = new JTextField(20);
    ageTextField.setEditable(false);
    
    JDateChooser dateChooser = new JDateChooser(new Date());
    dateChooser.addPropertyChangeListener("date", new PropertyChangeListener() {
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            Calendar dateofBirth = Calendar.getInstance();
            dateofBirth.setTime((Date)evt.getNewValue());
    
            Calendar today = Calendar.getInstance();
            int age = today.get(Calendar.YEAR) - dateofBirth.get(Calendar.YEAR);
    
            if(today.get(Calendar.MONTH) < dateofBirth.get(Calendar.MONTH) ||
              (today.get(Calendar.MONTH) == dateofBirth.get(Calendar.MONTH) && today.get(Calendar.DAY_OF_MONTH) < dateofBirth.get(Calendar.DAY_OF_MONTH))) {                    
                age--;
            }
    
            ageTextField.setText(String.valueOf(age));
        }
    });
    

    See another example in the answer to this question:


    Off-topic

    About this line (and other similar ones) :

    dOB.setBounds(97, 52, 95, 20);
    

    The use of methods such as setBounds(), setLocation() or setSize() are strongly discouraged when working with Swing because these lead to exact position of components. It is Layout Managers responsibility to handle components size and positioning. These are interesting topics to to emphasize this point: