【问题标题】:key-bindings and holding down keys键绑定和按住键
【发布时间】:2012-08-31 22:18:42
【问题描述】:

我为 JTextArea 组件创建了一个键绑定。当被调用时,它会创建一个自身的新实例并将焦点设置在它上面。

如果你按住回车键(调用键绑定),我的程序将开始吐出一堆 JTextArea 实例。

有没有办法强制用户再次按回车键来创建一个新实例?

我是切换到 KeyListeners 还是有键绑定的方法?

【问题讨论】:

    标签: java swing jtextarea key-bindings keystrokes


    【解决方案1】:

    当您设置输入映射时,您指定 KeyStroke 仅在按键释放时触发

    见 KeyStroke getKeyStroke(int keyCode, int modifiers, boolean onKeyRelease)

    【讨论】:

    • @trashgod opps,本来是 Java 7 API,会更新,谢谢
    • @trashgod ps - 直到我在另一篇文章中读到它,我才知道它;)
    • 那不好。我需要它在按键时触发。但是,一旦它触发,我需要将其禁用,直到密钥释放。我使用了keylistener。我创建了一个布尔型按键,函数 keyPressed() 将其设置为 true,而 keyReleased() 将其设置为 false。如果是真的,keyPressed 里面的代码不能被执行,所以它运行得非常好......
    • @Karlovsky120 相同的概念可以应用于 Key Bindings,并且它们不会遇到与 KeyListener 相同的焦点问题
    【解决方案2】:

    使用键绑定的方法是有两个动作:

    • 创建组件的操作绑定到按下的回车,插入组件时它会禁用自身
    • 再次启用该操作的操作绑定到已释放的输入

    一些代码:

    // 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);
    

    请注意,相同的动作实例已注册到所有组件,因此哪个具有焦点并不重要(并最终再次启用创建)

    【讨论】:

      【解决方案3】:

      这是我使用的代码,仅在第一次按下键时才运行操作:

      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;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多