不转移焦点的JCheckBox助记符
JCheckBox mnemonic without transferring focus
根据标题,是否可以使用助记键更改JCheckBox
选择状态而不将焦点转移到组件?
根据 GIF 的当前行为。
想要的行为是将焦点留在“类型”文本字段上。
问题是来自 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
}
}
这深埋在复选框的键绑定处理中,并且此代码从未打算进行自定义。
解决方法是创建您自己的 class,它扩展 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;
}
}
}
鉴于助记词注册为按键绑定,在
的范围内
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
中表达的语义,我们覆盖了 pressed
和 released
操作以更改 ButtonModel
状态。
示例:
根据标题,是否可以使用助记键更改JCheckBox
选择状态而不将焦点转移到组件?
根据 GIF 的当前行为。
想要的行为是将焦点留在“类型”文本字段上。
问题是来自 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
}
}
这深埋在复选框的键绑定处理中,并且此代码从未打算进行自定义。
解决方法是创建您自己的 class,它扩展 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;
}
}
}
鉴于助记词注册为按键绑定,在
的范围内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
中表达的语义,我们覆盖了 pressed
和 released
操作以更改 ButtonModel
状态。
示例: