ActionListener on JOptionPane

user1521881 picture user1521881 · Oct 10, 2012 · Viewed 18.5k times · Source

I am following the Oracle tutorial on how to create a custom dialog box: http://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html

I have two buttons: Save Object and Delete Object which when clicked should execute a certain piece of code. Unfortunately I can't seem to add any ActionListener to the JOptionPane buttons so when they're clicked nothing happens.

Can anyone help tell me how I can go about doing this? Here is the class I have for the dialog box so far:

class InputDialogBox extends JDialog implements ActionListener, PropertyChangeListener {
    private String typedText = null;
    private JTextField textField;

    private JOptionPane optionPane;

    private String btnString1 = "Save Object";
    private String btnString2 = "Delete Object";

    /**
     * Returns null if the typed string was invalid;
     * otherwise, returns the string as the user entered it.
     */
    public String getValidatedText() {
        return typedText;
    }

    /** Creates the reusable dialog. */
    public InputDialogBox(Frame aFrame, int x, int y) {
        super(aFrame, true);

        setTitle("New Object");

        textField = new JTextField(10);

        //Create an array of the text and components to be displayed.
        String msgString1 = "Object label:";

        Object[] array = {msgString1, textField};

        //Create an array specifying the number of dialog buttons
        //and their text.
        Object[] options = {btnString1, btnString2};

        //Create the JOptionPane.
        optionPane = new JOptionPane(array,
                JOptionPane.PLAIN_MESSAGE,
                JOptionPane.YES_NO_OPTION,
                null,
                options,
                options[0]);


        setSize(new Dimension(300,250));
        setLocation(x, y);

        //Make this dialog display it.
        setContentPane(optionPane);
        setVisible(true);

        //Handle window closing correctly.
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);

        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent we) {
                /*
                 * Instead of directly closing the window,
                 * we're going to change the JOptionPane's
                 * value property.
                 */
                optionPane.setValue(new Integer(
                        JOptionPane.CLOSED_OPTION));
            }
        });

        //Ensure the text field always gets the first focus.
        addComponentListener(new ComponentAdapter() {
            public void componentShown(ComponentEvent ce) {
                textField.requestFocusInWindow();
            }
        });

        //Register an event handler that puts the text into the option pane.
        textField.addActionListener(this);

        //Register an event handler that reacts to option pane state changes.
        optionPane.addPropertyChangeListener(this);
    }

    /** This method handles events for the text field. */
    public void actionPerformed(ActionEvent e) {
        optionPane.setValue(btnString1);
        System.out.println(e.getActionCommand());
    }

    /** This method reacts to state changes in the option pane. */
    public void propertyChange(PropertyChangeEvent e) {
        String prop = e.getPropertyName();

        if (isVisible()
         && (e.getSource() == optionPane)
         && (JOptionPane.VALUE_PROPERTY.equals(prop) ||
             JOptionPane.INPUT_VALUE_PROPERTY.equals(prop))) {
            Object value = optionPane.getValue();

            if (value == JOptionPane.UNINITIALIZED_VALUE) {
                //ignore reset
                return;
            }

            //Reset the JOptionPane's value.
            //If you don't do this, then if the user
            //presses the same button next time, no
            //property change event will be fired.
            optionPane.setValue(JOptionPane.UNINITIALIZED_VALUE);
            if (btnString1.equals(value)) {
                    typedText = textField.getText();
                String ucText = typedText.toUpperCase();
                if (ucText != null ) {
                    //we're done; clear and dismiss the dialog
                    clearAndHide();
                } else {
                    //text was invalid
                    textField.selectAll();
                    JOptionPane.showMessageDialog(
                                InputDialogBox.this,
                                    "Please enter a label",
                                    "Try again",
                                    JOptionPane.ERROR_MESSAGE);
                    typedText = null;
                    textField.requestFocusInWindow();
                }
            } else { //user closed dialog or clicked delete
               // Delete the object ...

                typedText = null;
                clearAndHide();
            }
        }
    }

    /** This method clears the dialog and hides it. */
    public void clearAndHide() {
        textField.setText(null);
        setVisible(false);
    }

Answer

MadProgrammer picture MadProgrammer · Oct 11, 2012

I think you're missing the point of the JOptionPane. It comes with the ability to show it's own dialog...

public class TestOptionPane02 {

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

    public TestOptionPane02() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JTextField textField = new JTextField(10);

                String btnString1 = "Save Object";
                String btnString2 = "Delete Object";

                //Create an array of the text and components to be displayed.
                String msgString1 = "Object label:";
                Object[] array = {msgString1, textField};
                //Create an array specifying the number of dialog buttons
                //and their text.
                Object[] options = {btnString1, btnString2};

                int result = JOptionPane.showOptionDialog(null, array, "", JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE, "New Object", options, options[0]);
                switch (result) {
                    case 0:
                        System.out.println("Save me");
                        break;
                    case 1:
                        System.out.println("Delete me");
                        break;
                }
            }
        });
    }
}

To do it manually, you're going to have to do a little more work.

Firstly, you're going to have to listen to the panel's property change events, looking for changes to the JOptionPane.VALUE_PROPERTY and ignoring any value of JOptionPane.UNINITIALIZED_VALUE...

Once you detect the change, you will need to dispose of your dialog.

The you will need extract the value that was selected via the JOptionPane#getValue method, which returns an Object. You will have to interrupt the meaning to that value yourself...

Needless to say, JOptionPane.showXxxDialog methods do all this for you...

Now if you worried about having to go through all the setup of the dialog, I'd write a utility method that either did it completely or took the required parameters...but that's just me

UPDATED

Don't know why I didn't think it sooner...

Instead of passing an array of String as the options parameter, pass an array of JButton. This way you can attach your own listeners.

options - an array of objects indicating the possible choices the user can make; if the objects are components, they are rendered properly; non-String objects are rendered using their toString methods; if this parameter is null, the options are determined by the Look and Feel