Search code examples
javaswingnetbeansjdatechooser

How to detect if the user changed JDateChooser date and not anything else setting the date property?


I use JDateChooser to edit dates in my form.

Short version: I need to distinguish between user date edit and programmatical property change on a JDateChooser.

Workaround: I've found a protected JDateChooser property named dateSelected which is exactly what I need (afaics there is no getter) so probably I'd have to make my own extended JDateChooser class and make a getter for this property. The problem here is that I want to have this custom version to be draggable from the Netbeans Palette and my custom JDateChooser won't be.

Long version: First I get a date from my database and I use the JDateChooser's setDate() method to set the date in the GUI. I want to edit database's date when user picks a new date with the chooser. To do that i listen for a PropertyChange event on the JDateChooser object (looking for the "date" change). After settig the new date in the database, I want to refresh the data (I get the whole record from the database) and I set the date from the database (if there was any error, it gets set back to whatever is in the database at the moment).

The problem is that when I set the date from the database, the same event is fired whe user changes date and then my "refresh" mechanism updates the JDateChooser field and I get infinite loop.

My existing (simplified) code (netbeans):

private void dataStartuChooserPropertyChange(java.beans.PropertyChangeEvent evt) {
    if ("date".equals(evt.getPropertyName())) {
        JDateChooser wybieraczDat = (JDateChooser) evt.getSource();
        updateDatabaseField(wybieraczDat.getDate());
    }
}

Solution

  • I will reply to myself here because I fould a crazy way of doing this (which potentially can be worthless, but is fine for my needs). I will not create a complete working example because I dont have the time. Still some1 may benefit.

    To check wether date was chosen by user or set programatically in a PropertyChangeEvent of a JDateChooser I check a JDateChooser's private field called dateSelected. After I do whatever is needed (modifying database) I set this field back to false because otherwise it would stay true even if date was changed programatically again. Sample (unoptimized, ugly, only to demonstrate what I did) code below.

    JDateChooser aDateChooserInstance = new JDateChooser();
    
    // Listen for property changes
    aDateChooserInstance.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
        public void propertyChange(java.beans.PropertyChangeEvent evt) {
            // If the 'date' property was changed...
            if ("date".equals(evt.getPropertyName())) {
                JDateChooser aDateChooser = (JDateChooser) evt.getSource();
                boolean isDateSelectedByUser = false;
                // Get the otherwise unaccessible JDateChooser's 'dateSelected' field.
                try {
                    // Get the desired field using reflection
                    Field dateSelectedField = JDateChooser.class.getDeclaredField("dateSelected");
                    // This line makes the value accesible (can be read and/or modified)
                    dateSelectedField.setAccessible(true);
                    isDateSelectedByUser = dateSelectedField.getBoolean(aDateChooser);
                } catch (Exception ignoreOrNot) {
                }
    
                // Do some important stuff depending on wether value was changed by user
                if (isDateSelectedByUser) {
                    importantStuff();
                }
    
                // Reset the value to false
                try {
                    Field dateSelectedField = JDateChooser.class.getDeclaredField("dateSelected");
                    dateSelectedField.setAccessible(true);
                    isDateSelectedByUser = dateSelectedField.setBoolean(aDateChooser, false);
                } catch (Exception ignoreOrNot) {
                }
            }
        }
    });