kneedhelp
kneedhelp

Reputation: 705

Add key bindings to JButtons that get their actions from action commands?

I found a cool way in another question to create a JButton whose actions are written and viewed in an easy way:

public JButton makeToolbarButton(String title, String actionCommand) {
    JButton button = new JButton(title);
    button.setActionCommand(actionCommand);
    button.addActionListener(this);
    return button;
}

The class this method is in implements ActionListener, and the buttons commands are assigned by:

public void actionPerformed(ActionEvent e) {
    int action = Integer.parseInt(e.getActionCommand());
    switch(action) {
        case 1:
            System.out.println("This button pressed.");
        break;
    }
}

And the buttons are made by:

    JButton button1 = makeToolbarButton("Button 1", "1");

So my question is: can I add KeyStrokes to a button by this method? I tried something like this (inside of the makeToolbarButton method):

    button.getInputMap().put(KeyStroke.getKeyStroke("B"), "button_pressed");
    button.getActionMap().put("button_pressed", button.getAction());

But I figure this doesn't work because the action command isn't actually assigning an action to a specific button. Is there a way to add something to the makeToolbarButton() method and a parameter for the KeyStroke to accomplish this?

Upvotes: 1

Views: 711

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347334

I think you're missing the point of the Action API. A Action is intended to provide a single, self contained, unit of work. This means that the actionCommand really isn't required, as when the actionListener event is triggered, you know exactly the context in which it's been executed

I'd also avoid using KeyStroke.getKeyStroke(String), as the text is a verbose description of what you want to do (ie pressed B or something, but needless to say, it's a pain to get right)

So, the following demonstrates how you might use Actions and assign them to a button AND a key binding

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class ActionTest {

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

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

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            add(createButton(new ActionOne(), KeyStroke.getKeyStroke(KeyEvent.VK_1, 0)));
            add(createButton(new ActionTwo(), KeyStroke.getKeyStroke(KeyEvent.VK_2, 0)));
        }

        public JButton createButton(Action action, KeyStroke keyStroke) {
            JButton btn = new JButton(action);
            btn.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(keyStroke, "button_pressed");
            btn.getActionMap().put("button_pressed", action);
            return btn;
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.dispose();
        }

    }

    public class ActionOne extends AbstractAction {

        public ActionOne() {
            putValue(NAME, "1");
            putValue(Action.ACTION_COMMAND_KEY, "Action.one");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println(e.getActionCommand());
        }

    }

    public class ActionTwo extends AbstractAction {

        public ActionTwo() {
            putValue(NAME, "2");
            putValue(Action.ACTION_COMMAND_KEY, "Action.two");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println(e.getActionCommand());
        }

    }

}

See How to Use Actions for more details

Upvotes: 4

Related Questions