Home > front end >  Multiple Key KeyStroke for Menu Shortcuts in Java
Multiple Key KeyStroke for Menu Shortcuts in Java

Time:04-01

I am working on a program that maintains data for multiple different purposes, such as loads, vehicle service, brokers, customers, fuel purchases, as well as other types of purchases.

To this end, I have used a JMenu to contain the menu items for creating these new data items. So, the user can press, for example, ALT N, L to open the new load wizard. This is just simple menu navigation.

Is there also a way to create a keyboard shortcut, such as CTLR N, L that would do basically the same thing, but without opening the menus?

What I mean is, the user presses CTLR N and the system waits for another key, which would be L for new loads, B for new broker entry, etc. I was using some program (I can't remember which program off-hand) that had functionality like this. I don't know what language it was written in, but I remember thinking that it was cool that the developers had created multiple hot keys based off of standard keyboard shortcuts by simply waiting for a third key to be pressed separately from the CTRL ${KEY} combination.

I have been searching online for an idea of how to accomplish this feat, but am not seeing anything close to what I am looking for. Just to be clear about what I am trying to do, look at the following:

  • I have a module for handling the load tracking data, which comes with a wizard for entering new loads. To launch this wizard, I would like the keyboard shortcut to be displayed on the New...Load Wizard menu item as CTRL N, L. When the user presses CTRL N the application waits to see what key is pressed next. If the next key pressed is N, then the New Load Wizard is launched.
  • I have a module for handling the broker data, which has a data entry dialog for entering new brokers. To open this dialog, I would like the keyboard shortcut to be displayed on the New...Broker menu item as CTRL N, B. When the user presses CTRL N the application waits to see what key is pressed next. If the next key pressed is B, then the New Broker dialog is displayed.
  • I have a module for handling vehicle services, maintenance, and repairs, which has a single dialog for entering the information regarding these purchases. I would like the keyboard shortcut to be displayed on the New...Service/Repair menu item as CTRL N, S. When the user presses CTRL N the application waits to see what key is pressed next. If the next key pressed is S, then the New Service/Repair dialog is opened.
  • There will be a similar menu item under the New menu for the other modules in the application, which should function the same way.
  • If the key pressed after the CTRL N KeyStroke is not one of the available single shortcut keys displayed on the various New menu items, then it cancels the wait for the next key press. In other words, if the user presses CTRL N, then presses, for example, Z (which has no menu item associated with it) the CTRL N is simply discarded.

I am not sure if I have explained what I am trying to do clearly enough, so am more than willing to answer questions to allow for better understanding of my thoughts. Even so, any ideas or thoughts are greatly appreciated!

-SC

CodePudding user response:

This is how I did it.

I set a flag after the user presses Ctrl N and then if the user presses b, perform the appropriate action if the flag is set.

The below code is simply a proof of concept (POC).

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;

public class BindKeys {
    private boolean  flag;
    private JTextField  textField;

    private JPanel createButton() {
        JPanel panel = new JPanel();
        JButton button = new JButton("Exit");
        button.addActionListener(e -> System.exit(0));
        panel.add(button);
        return panel;
    }

    private JPanel createTextField() {
        JPanel panel = new JPanel();
        panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
        textField = new JTextField(12);
        InputMap im = textField.getInputMap();
        KeyStroke ctrlN = KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_DOWN_MASK);
        im.put(ctrlN, "SET_FLAG");
        KeyStroke b = KeyStroke.getKeyStroke('b');
        im.put(b, "NEW_BROKER");
        ActionMap am = textField.getActionMap();
        am.put("SET_FLAG", new CtrlNAction());
        am.put("NEW_BROKER", new BAction());
        
        panel.add(textField);
        return panel;
    }

    private void showGui() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(createTextField(), BorderLayout.PAGE_START);
        frame.add(createButton(), BorderLayout.PAGE_END);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private class BAction extends AbstractAction {
        public void actionPerformed(ActionEvent event) {
            if (flag) {
                textField.setText("New broker");
            }
            else {
                textField.setText(textField.getText()   "b");
            }
        }
    }

    private class CtrlNAction extends AbstractAction {
        public void actionPerformed(ActionEvent event) {
            flag = true;
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> new BindKeys().showGui());
    }
}

Refer to How to Use Key Bindings

  • Related