7

How can I set a cancel button in a Swing JDialog, i.e. a button whose action is performed automatically if the user presses the “Cancel” key on the keyboard?

The counterpart is offered for a default action via the setDefaultButton method of the dialog's root pane.

If that's helping, I'm searching for an analogue to the WinForms Form.CancelButton property.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214

4 Answers4

4

The best way I can see is to add an Action to the action map of the root pane, and link that action to the escape key using the root pane's input map.

For this, you need an Action. If your cancel button's behaviour is implemented as an action (ie. cancelButton.getAction() != null), then this will work:

getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "CANCEL");
getRootPane().getActionMap().put("CANCEL", cancelButton.getAction());

Otherwise, if the cancel button's logic is implemented via an ActionListener, you could have the actionPerformed() method of the ActionListener call a private void onCancel() method that implements the logic, and register a "cancel" action that calls the same method.

getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "CANCEL");
getRootPane().getActionMap().put("CANCEL", new AbstractAction(){
    @Override
    public void actionPerformed(ActionEvent e)
    {
        onCancel();
    }
});
Jon Bright
  • 13,388
  • 3
  • 31
  • 46
Jesse
  • 3,751
  • 1
  • 21
  • 19
2

Single line solution

t.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
   .put(KeyStroke.getKeyStroke("ESCAPE"), btnCancel.getAction());

where t is any component(except JButton) like JTextField in the dialog.

Prabu
  • 2,313
  • 2
  • 28
  • 31
  • 1
    The second argument to the `put()` method is a key into the action map, not an `Action`. This would only work if `btnCancel.getAction() != null`, and if the `Action` returned by `btnCancel.getAction()` was registered in the action map for `t` with itself as the key, ie. if `t.getActionMap().put(btnCancel.getAction(), btnCancel.getAction())` had previously been called. – Jesse Mar 05 '12 at 15:32
1

I don't think this is possible with JDialog without extending it.

You could use JOptionPane.showOptionDialog() (or possibly one of the other show methods), passing the JButtons you want to be used.

If the options passed are components, they'll be rendered as normal, so you can do something like this:

int optionType = JOptionPane.DEFAULT_OPTION;
int messageType = JOptionPane.PLAIN_MESSAGE; // no standard icon

JButton ok = new JButton("ok");
JButton cancel = new JButton("cancel");
//add any handlers to the buttons
...
//construct options
Object[] selValues = { ok, cancel };

//show dialog as normal, selected index will be returned.
int res = JOptionPane.showOptionDialog(null, "message",
        "title", optionType, messageType, null, selValues,
        selValues[0]);
Rich Seller
  • 83,208
  • 23
  • 172
  • 177
  • Hi Rich, thanks for the example. Unfortunately, I need a completely customized dialog with lots of different controls, not merely an individualized option dialog. As far as I can see, there's no method/overload that can be passed a completely customized panel. – Konrad Rudolph Aug 16 '09 at 14:16
  • 1
    I think you're right, if you have a custom dialog, you will need to implement the handling yourself, you can however rip off the processing to do so from JOptionPane. FWIW in SWT you can define an arbitrary subclass of Dialog and call its open() method to display it – Rich Seller Aug 16 '09 at 14:23
1

All you have to do is attach the action listener to the button and call dialog.setVisible(false) inside of it.

Eugene Ryzhikov
  • 17,131
  • 3
  • 38
  • 60
  • You don't answer the question. It was about to dismiss a dialog with a keystroke, in general with the Escape key. At least that's how I read the question, which is a bit ambiguous on re-reading it. – PhiLho Aug 17 '09 at 05:43
  • Oops, thanks for pointing that out. The question should read “‘cancel’ key,” not “button”. I’ll fix that. – Konrad Rudolph Aug 17 '09 at 06:58