【问题标题】:JCheckBox mnemonic without transferring focus不转移焦点的 JCheckBox 助记符
【发布时间】:2021-02-11 21:06:26
【问题描述】:

根据标题,是否可以使用 助记键 更改 JCheckBox 选择状态而不将焦点转移到组件?

根据 GIF 的当前行为。
想要的行为将焦点留在“类型”文本字段上。

【问题讨论】:

  • 使用标准的 JCheckBox,您只能使用 setFocusable(false); 来实现这一点 - 但是您不能再使用 tab 键来选择复选框,然后按空格键来切换它。
  • @ThomasKläger 如果我能拦截助记符事件就好了。但我找不到办法
  • @ThomasKläger 顺便说一句,解决方法没问题。
  • 您可以使用Key Bindings,而不是使用助记符。
  • @camickr 是否仍然可以用您的策略突出显示 ALT 上的“假助记符”字母?

标签: java swing focus mnemonics


【解决方案1】:

问题在于BasicButtonListener.Actions 中的这些行:

        if (key == PRESS) {
            ButtonModel model = b.getModel();
            model.setArmed(true);
            model.setPressed(true);
            if(!b.hasFocus()) {
                b.requestFocus();  // here it requests the focus
            }
        }

这在复选框的键绑定处理中深藏不露,而且这段代码从来没有被定制过。

一种解决方法是创建您自己的扩展 JCheckBox 的类,特别是在处理键绑定时不请求焦点:

public class MyCheckBox extends JCheckBox {

    private boolean requestFocusAllowed = true;

    public MyCheckBox() {
    }

    @Override
    public void requestFocus() {
        if (requestFocusAllowed) {
            super.requestFocus();
        }
    }

    @Override
    protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
        requestFocusAllowed = false;
        try {
            return super.processKeyBinding(ks, e, condition, pressed);
        } finally {
            requestFocusAllowed = true;
        }
    }
}

【讨论】:

  • 谢谢!这似乎是一个类似于 camickr 在 cmets 中提出的想法。我想然后助记符被注册为键绑定,那么如果我只是通过使用相同的组合键注册一个新的来覆盖它呢?
  • 我已经实现了我上面提到的,随时提出你的意见。
【解决方案2】:

鉴于助记词被注册为键绑定,在

的范围内
JComponent.WHEN_IN_FOCUSED_WINDOW

BasicButtonListener#updateMnemonicBinding


我们可以简单地用我们自己的来覆盖键绑定操作。

private class MnemonicCheckBox : JCheckBox(...) {
  override fun setMnemonic(mnemonic: Int) {
    super.setMnemonic(mnemonic)

    if (mnemonic != 0) {
      overrideMnemonicActions()
    }
  }

  private fun overrideMnemonicActions() {
    val mnemonicMask = UIUtilities.getSystemMnemonicKeyMask()
    val altGraphDownMask = InputEvent.ALT_GRAPH_DOWN_MASK

    getInputMap(WHEN_IN_FOCUSED_WINDOW).apply {
      // Pressed
      put(KeyStroke.getKeyStroke(mnemonic, mnemonicMask), "mnemonicPressed")
      put(KeyStroke.getKeyStroke(mnemonic, mnemonicMask or altGraphDownMask), "mnemonicPressed")

      // Released
      put(KeyStroke.getKeyStroke(mnemonic, mnemonicMask, true), "mnemonicReleased")
      put(KeyStroke.getKeyStroke(mnemonic, mnemonicMask or altGraphDownMask, true), "mnemonicReleased")
    }

    actionMap.apply {
      put("mnemonicPressed", object : AbstractAction() {
        override fun actionPerformed(event: ActionEvent) {
          model.isArmed = true
          model.isPressed = true
        }
      })
      put("mnemonicReleased", object : AbstractAction() {
        override fun actionPerformed(event: ActionEvent) {
          model.isPressed = false
          model.isArmed = false
        }
      })
    }
  }
}

为了保持BasicButtonListener.Actions 中表达的语义,我们重写了pressedreleased 操作以更改ButtonModel 状态。

例子:

【讨论】:

    猜你喜欢
    • 2013-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多