Search code examples
javaswingjoptionpanejdialogpropertychanged

JDialog property changed behaviour


I have implemented a JDialog which is along the lines of the top answer seen in this previous question. The code works entirely apart from the fact that when an invalid input is provided, two PropertyChangedEvents occur when only one is desired. This led to the formulation of the SSCCE below:

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;

public class Test{  
    public Test(){
        JOptionPane optionPane = new JOptionPane(null, JOptionPane.OK_CANCEL_OPTION);

        final JDialog dialog = new JDialog(new JFrame(), "Test", true);
        dialog.setContentPane(optionPane);

        optionPane.addPropertyChangeListener(new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent e) {
                String prop = e.getPropertyName();

                if (dialog.isVisible() && (e.getSource() == optionPane) && (JOptionPane.VALUE_PROPERTY.equals(prop))){
                    java.lang.System.out.println("Code Reached");
                    optionPane.setValue(JOptionPane.UNINITIALIZED_VALUE);
                }
            }
        });
        dialog.pack();
        dialog.setVisible(true);
    }

    public static void main(String[] args){
        new Test();
    }
}

From this SSCCE, it is possible to tell that the second, and unwanted, PropertyChangedEvent is caused by the line of code optionPane.setValue(JOptionPane.UNINITIALIZED_VALUE); this code however is neccessary to prevent the window locking up after invalid inputs. Is there a way to either prevent the JOptionPane.setValue() from causing a PropertyChangedEvent, or to determine when the PropertyChangedEventhas been caused by resetting the value of the JOptionPane and prevent the if occuring? Thanks.


Solution

  • If it's possible for you to disable the event listener, you could do it by:

    A) set a (boolean) flag in the PropertyChangeListener object

    or

    B) remove the eventlistener from the optionPane:

    final PropertyChangeListener pcl = new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent e) {
            String prop = e.getPropertyName();
    
            if (dialog.isVisible() && (e.getSource() == optionPane) && (JOptionPane.VALUE_PROPERTY.equals(prop))){
                java.lang.System.out.println("Code Reached");
                optionPane.setValue(JOptionPane.UNINITIALIZED_VALUE);
    
                optionPane.removePropertyChangeListener(pcl);
            }
        }
    }
    optionPane.addPropertyChangeListener(pcl);
    

    However, this depends on the dialogs purpose. If you close the dialog, then option B is good.

    EDIT:

    The second event is caused by optionPane.setValue(JOptionPane.UNINITIALIZED_VALUE) , so if you check against that value, it could work.

    if (dialog.isVisible() 
            && e.getSource() == optionPane 
            && JOptionPane.VALUE_PROPERTY.equals(prop)
            && !optionPane.getValue().equals(JOptionPane.UNINITIALIZED_VALUE)){
    
        java.lang.System.out.println("Code Reached");
        optionPane.setValue(JOptionPane.UNINITIALIZED_VALUE);
    }