在每个窗口/面板中,我将Enter键映射为defaultButton(意味着即使按下的按钮未对焦,按Enter也会触发按钮按下)。我需要做的是将Escape键映射到另一个按钮,该按钮也会触发第二个按钮,无论焦点如何。输入键的代码是:
// We get the button
IButton iButton = (IButton)actionToolbar.getComponent(actionToolbar.getComponentCount() - 1);
// We get the window
Window window = SwingUtilities.getWindowAncestor(this);
// Only these two types of windows should have this behaviour
if (window instanceof JFrame) {
((JFrame)window).getRootPane().setDefaultButton(iButton);
}
else if (window instanceof JDialog) {
((JDialog)window).getRootPane().setDefaultButton(iButton);
}
现在我需要的是基本相同的代码,但是改变了Enter with Escape,或者添加了一个监听器....我不确定是什么。
编辑:我必须在Java 1.4中执行此操作,我知道如果我立即说出来会很棒。答案 0 :(得分:4)
JXRootPane(SwingX项目)默认情况下,您可以执行类似
的操作private void installKeyboardActions() {
Action escAction = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent evt) {
JButton cancelButton = getCancelButton();
if (cancelButton != null) {
cancelButton.doClick(20);
}
}
/**
* Overridden to hack around #566-swing:
* JXRootPane eats escape keystrokes from datepicker popup.
* Disable action if there is no cancel button.<p>
*
* That's basically what RootPaneUI does - only not in
* the parameterless isEnabled, but in the one that passes
* in the sender (available in UIAction only). We can't test
* nor compare against core behaviour, UIAction has
* sun package scope. <p>
*
* Cont'd (Issue #1358-swingx: popup menus not closed)
* The extended hack is inspired by Rob Camick's
* <a href="http://tips4java.wordpress.com/2010/10/17/escape-key-and-dialog/"> Blog </a>
* and consists in checking if the the rootpane has a popup's actionMap "inserted".
* NOTE: this does not work if the popup or any of its children is focusOwner.
*/
@Override
public boolean isEnabled() {
Component component = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
if (component instanceof JComponent) {
Action cancelPopup = ((JComponent)component).getActionMap().get("cancel");
if (cancelPopup != null) return false;
}
return (cancelButton != null) && (cancelButton.isEnabled());
}
};
getActionMap().put("esc-action", escAction);
InputMap im = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
im.put(key, "esc-action");
}
/**
* Sets the <code>cancelButton</code> property,
* which determines the current default cancel button for this <code>JRootPane</code>.
* The cancel button is the button which will be activated
* when a UI-defined activation event (typically the <b>ESC</b> key)
* occurs in the root pane regardless of whether or not the button
* has keyboard focus (unless there is another component within
* the root pane which consumes the activation event,
* such as a <code>JTextPane</code>).
* For default activation to work, the button must be an enabled
* descendant of the root pane when activation occurs.
* To remove a cancel button from this root pane, set this
* property to <code>null</code>.
*
* @param cancelButton the <code>JButton</code> which is to be the cancel button
* @see #getCancelButton()
*
* @beaninfo
* description: The button activated by default for cancel actions in this root pane
*/
public void setCancelButton(JButton cancelButton) {
JButton old = this.cancelButton;
if (old != cancelButton) {
this.cancelButton = cancelButton;
if (old != null) {
old.repaint();
}
if (cancelButton != null) {
cancelButton.repaint();
}
}
firePropertyChange("cancelButton", old, cancelButton);
}
/**
* Returns the value of the <code>cancelButton</code> property.
* @return the <code>JButton</code> which is currently the default cancel button
* @see #setCancelButton
*/
public JButton getCancelButton() {
return cancelButton;
}
答案 1 :(得分:1)
或另一种非常简单的方法
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class ExampleKeyStrokes {
private JFrame frame = new JFrame();
private JButton button;
public ExampleKeyStrokes() {
button = new JButton(new AbstractAction(" push ENTER ") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
button.setText(" Please push ENTER ");
//button.setPreferredSize(new Dimension(200, 50));
frame.add(button);
frame.getRootPane().setDefaultButton(button);
frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("F2"), "clickButton");
frame.getRootPane().getActionMap().put("clickButton", new AbstractAction() {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
button.doClick();
}
});
frame.setLocation(150, 150);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
setFocusButton();
}
private void setFocusButton() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
button.grabFocus();
button.requestFocus();
button.requestFocusInWindow();
}
});
}
static public void main(String[] s) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ExampleKeyStrokes eKS = new ExampleKeyStrokes();
}
});
}
}
答案 2 :(得分:1)
我设法通过向打开的面板添加一个键监听器来解决这个问题,比如
InputMap iMap = theTaskWindow.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "escape");
ActionMap aMap = theTaskWindow.getRootPane().getActionMap();
aMap.put("escape", new AbstractAction() {
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e){
doCancel();
}
});
答案 3 :(得分:-1)
这样做:
window.getContentPane().registerKeyboardAction(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onCancel();
}
}, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
你的第二个JButton也应该在点击时调用onCancel()。因此,无论是按下逃生还是点击这两个都会做同样的事情。