javakey-bindingsaction-mapping

How do I bind a key to a JButton?


I have a simple JButton linked to an actionPerformed method. Now I want to bind a key to the button so that when i press this key on the keyboard it performs the same action it would perform by pressing the button with the mouse.

I found out this code is working but as you can see I have to write twice the code to perform when key is pressed or button is pressed.

Is there a way to avoid this?

import java.io.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.*;


public class provakey implements ActionListener{

    private JButton bStart;                                         
    
    //Costruttore
    public provakey() throws IOException{
        initGUI();
    }

    private void initGUI(){
        JFrame frame = new JFrame();
        JPanel buttonPanel = new JPanel();
        bStart = new JButton("Avvia");
        bStart.addActionListener(this);
        bStart.setActionCommand("start");
        bStart.setBounds(140,10,150,40);

        AbstractAction buttonPressed = new AbstractAction() {   
            @Override
            public void actionPerformed(ActionEvent e) {
                if (bStart.isEnabled()){

                System.out.println("pressed");
                }
            }
        };
        bStart.getActionMap().put("start", buttonPressed);
        bStart.getInputMap(javax.swing.JComponent.WHEN_IN_FOCUSED_WINDOW).
                put(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_A,0), "start");

        buttonPanel.setLayout(null);
        buttonPanel.setBounds(0,240,600,60);
        buttonPanel.add(bStart);
        frame.setLayout(null);
        frame.add(buttonPanel);
        frame.setTitle("Prova");
        frame.setSize(600, 350);
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
        if ("start".equals(e.getActionCommand())) { 
            buttonPressed();
        }
    }

    public void buttonPressed(){
        System.out.println("pressed");
    }

    public static void main (String args[]) throws IOException {
        provakey p = new provakey();
    }
}

Solution

  • I have to write twice the code to perform when key is pressed or button is pressed.

    An Action is an ActionListener.

    So, you can add an Action to the button, so the same Action will be executed whether you click on the button or use the key binding:

    //bStart.addActionListener(this);
    bStart.addActionListener( buttonPressed );
    

    There is no need to set the action command since you now have a unique class for your "Start" processing that is not shared by other buttons in your class.

    See: https://stackoverflow.com/a/33739732/131872 for a working example.