привязки клавиш и удерживание клавиш

Я создал привязку клавиш для компонента JTextArea. При вызове он создает новый экземпляр самого себя и устанавливает на него фокус.

Если вы удерживаете клавишу ввода (которая вызывает привязку клавиш), моя программа начнет выдавать кучу экземпляров JTextArea.

Есть ли способ заставить пользователя нажать Enter еще раз, чтобы создать новый экземпляр?

Я должен переключиться на KeyListeners или есть способ с привязкой клавиш?


person Karlovsky120    schedule 31.08.2012    source источник


Ответы (3)


способ сделать это с помощью сочетаний клавиш состоит в том, чтобы иметь два действия:

  • действие, создающее компонент, привязано к нажатому вводу, оно само отключается при вставке компонента
  • действие, разрешающее действие снова, привязано к освобожденному вводу

Некоторый код:

// the action to create the component
public static class CreateAction extends AbstractAction {

    private Container parent;
    private Action enableAction;

    public CreateAction(Container parent) {
        this.parent = parent;
        enableAction = new EnableAction(this);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        setEnabled(false);
        Component field = createTextField();
        parent.add(field);
        parent.revalidate();
        field.requestFocus();
    }

    int count;
    private Component createTextField() {
        // just for fun counting the fields we create
        JTextField field = new JTextField("field: " + count++, 20);
        field.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), 
                "createComponent");
        field.getActionMap().put("createComponent", this);
        field.getInputMap().put(KeyStroke.getKeyStroke("released ENTER"), 
                "enableCreation");
        field.getActionMap().put("enableCreation", enableAction);
        return field;
    }

}

// the action that enables another
public static class EnableAction extends AbstractAction {

    Action toEnable;

    public EnableAction(Action toEnable) {
        this.toEnable = toEnable;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        toEnable.setEnabled(true);
    }

}

// usage
final JComponent parent = new JPanel(new MigLayout("wrap"));
// here I'm lazy and let the action create the very first component as well
add.actionPerformed(null);
add.setEnabled(true);

Обратите внимание, что одни и те же экземпляры действий регистрируются для всех компонентов, поэтому не имеет значения, какой из них имеет фокус (и в конечном итоге снова разрешает создание).

person kleopatra    schedule 01.09.2012

Вы указываете, что KeyStroke срабатывает только при отпускании клавиши, когда вы настраиваете карту ввода.

См. KeyStroke getKeyStroke(int keyCode, int modifiers, логическое значение onKeyRelease)

person MadProgrammer    schedule 31.08.2012
comment
@trashgod opps, должен был быть API Java 7, обновится, спасибо - person MadProgrammer; 01.09.2012
comment
@trashgod ps - я не знал об этом, пока не прочитал это здесь, в другом посте;) - person MadProgrammer; 01.09.2012
comment
Это не хорошо. Мне нужно, чтобы он срабатывал при нажатии клавиши. Однако, как только он сработает, мне нужно, чтобы он был отключен до отпускания клавиши. Я использовал ключевой прослушиватель. Я создал логическое значение нажатия клавиши, и функция keyPressed() устанавливает для него значение true, а keyReleased() устанавливает для него значение false. Если это правда, код внутри keyPressed не может быть выполнен, поэтому он работает очень хорошо... - person Karlovsky120; 01.09.2012
comment
@ Karlovsky120 Та же концепция может быть применена к привязкам клавиш, и они не страдают от тех же проблем с фокусом, что и KeyListener. - person MadProgrammer; 27.04.2013

Вот код, который я использую, чтобы действие выполнялось только при первом нажатии клавиши:

private void registerKeyBindings(final JFrame frame) {
    var inputMap = frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
    inputMap.put(KeyStroke.getKeyStroke(KeyCode.G.getInputEventCode(), 0, false), "g_down");
    inputMap.put(KeyStroke.getKeyStroke(KeyCode.G.getInputEventCode(), 0, true), "g_up");
    
    frame.getRootPane().getActionMap().put("g_down", new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        if (gDown) return;
        gDown = true;

        // put your custom key-down-action code here
      }
    });
    frame.getRootPane().getActionMap().put("g_up", new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        gDown = false;
      }
    });
}
Boolean gDown = false;
person Venryx    schedule 22.05.2021