0

I have a Swing gui I'm working on. I have a "Save" button, and I want it to delete an entry instead of saving if it's clicked when the Alt key is held down. Checking whether alt is held when the button is clicked is no problem. That's not what this question is about.

I want the text of the "Save" button to change to "Delete" when Alt is pressed, and back to "Save" when Alt is released.

I've tried adding a KeyListener to my JPanel but it doesn't seem to activate, possibly because the panel itself doesn't have the focus because focus is on one of its children.

I've tried a key binding via JComponent InputMap and ActionMap, but I can't figure out a KeyStroke which corresponds to just the Alt key. My unsuccessful best guess at how that would look:

myPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("alt"), "altKey");
myPanel.getActionMap().put("altKey", new AbstractAction() {
    @Override
    public void actionPerformed(ActionEvent event) {
        log.info("alt has been pressed.");
        saveButton.setText(event.getModifiers() == KeyEvent.VK_ALT ? "Delete" : "Save");
    }
});

How can I get code to execute when the Alt key itself is pressed/released, regardless of where the focus is in the window?

Mar
  • 7,765
  • 9
  • 48
  • 82
  • You listening to the wrong event. `ActionEvent` is used when an user action is exerted on a Swing (or AWT) component. You need listen for a `KeyEvent`, specifically, the ALT key press. – hfontanez Jan 25 '22 at 21:08
  • 2
    Try the answer to [Listen to key events across all components](https://stackoverflow.com/a/5345036/16653700). – Alias Cartellano Jan 25 '22 at 21:09
  • This is a good read on Key Events and how to listen for them: https://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html – hfontanez Jan 25 '22 at 21:12
  • @AliasCartellano I've got a working KeyEventDispatcher that correctly detects if Alt is pressed/released. There seems to be a delay *sometimes* between when I press Alt and when the key event is dispatched. – Mar Jan 25 '22 at 21:18
  • @Martin for key binding, you may want to try `KeyStroke.getKeyStroke(KeyEvent.VK_ALT, InputEvent.ALT_DOWN_MASK)` – hfontanez Jan 25 '22 at 21:20

1 Answers1

1

To handle key events regardless of which element currently has the focus, use a KeyEventDispatcher attached to the current KeyboardFocusManager, e.g.:

KeyboardFocusManager.getCurrentKeyboardFocusManager()
    .addKeyEventDispatcher((KeyEvent event) -> {
        if (event.isAltDown()) {
            saveButton.setText("Delete");
        } else {
            saveButton.setText("Save");
        }
        return false; // `false` allows further handling by other code
    });

Thanks to @AliasCartellano

Note: there does seem to be a small, unpredictable delay between when you press the Alt key and when the event fires. Maybe because it's a modifier key? I'm unclear on whether that delay can be eliminated.

Mar
  • 7,765
  • 9
  • 48
  • 82