Java KeyListener vs Keybinding

后端 未结 2 1053
眼角桃花
眼角桃花 2020-11-29 13:12

i am trying to write a calculator and having a problem. I already made a actionlistener for all buttons and now i want to make it possible to input data from keyboard. DO i

相关标签:
2条回答
  • 2020-11-29 13:39

    A simple example that uses a single Action and supports Key Bindings to enter numbers:

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.border.*;
    
    public class CalculatorPanel extends JPanel
    {
        private JTextField display;
    
        public CalculatorPanel()
        {
            Action numberAction = new AbstractAction()
            {
                @Override
                public void actionPerformed(ActionEvent e)
                {
                    display.setCaretPosition( display.getDocument().getLength() );
                    display.replaceSelection(e.getActionCommand());
                }
            };
    
            setLayout( new BorderLayout() );
    
            display = new JTextField();
            display.setEditable( false );
            display.setHorizontalAlignment(JTextField.RIGHT);
            add(display, BorderLayout.NORTH);
    
            JPanel buttonPanel = new JPanel();
            buttonPanel.setLayout( new GridLayout(0, 5) );
            add(buttonPanel, BorderLayout.CENTER);
    
            for (int i = 0; i < 10; i++)
            {
                String text = String.valueOf(i);
                JButton button = new JButton( text );
                button.addActionListener( numberAction );
                button.setBorder( new LineBorder(Color.BLACK) );
                button.setPreferredSize( new Dimension(50, 50) );
                buttonPanel.add( button );
    
                KeyStroke pressed = KeyStroke.getKeyStroke(text);
                InputMap inputMap = button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
                inputMap.put(pressed, text);
                button.getActionMap().put(text, numberAction);
            }
        }
    
        private static void createAndShowUI()
        {
    //      UIManager.put("Button.margin", new Insets(10, 10, 10, 10) );
    
            JFrame frame = new JFrame("Calculator Panel");
            frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
            frame.add( new CalculatorPanel() );
            frame.pack();
            frame.setLocationRelativeTo( null );
            frame.setVisible(true);
        }
    
        public static void main(String[] args)
        {
            EventQueue.invokeLater(new Runnable()
            {
                public void run()
                {
                    createAndShowUI();
                }
            });
        }
    }
    

    Of course you would still need to create unique Actions for each operation you wish to support.

    0 讨论(0)
  • 2020-11-29 13:51

    Generally speaking, where you have a limited set of key inputs, key bindings are a better choice.

    KeyListener suffers from issues related to focusability and with other controls in the GUI, focus will constantly be moving away from the component (with the KeyListener) all the time.

    A simple solution would be to use the Actions API. This allows you to define a self contained "action" which acts as a ActionListener but also carries configuration information that can be used to configure other UI components, in particular, buttons

    For example...

    Take a generic NumberAction which could represent any number (lets limit it to 0-9 for now)...

    public class NumberAction extends AbstractAction {
    
        private int number;
    
        public NumberAction(int number) {
            putValue(NAME, String.valueOf(number));
        }
    
        public int getNumber() {
            return number;
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
            int value = getNumber();
            // Do something with the number...
        }
    
    }
    

    You could do something like...

    // Create the action...
    NumberAction number1Action = new NumberAction(1);
    // Create the button for number 1...
    JButton number1Button = new JButton(number1Action);
    
    InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
    // Create a key mapping for number 1...
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_1, 0), "number1");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD1, 0), "number1");
    
    ActionMap am = getActionMap();
    // Make the input key to the action...
    am.put("number1", number1Action);
    

    And you're done...

    You can also create any number of instance of the NumberAction for the same number, meaning you could configure the UI and the bindings separately, but know that when triggered, they will execute the same code logic, for example...

    0 讨论(0)
提交回复
热议问题