Java 如何防止在文本区域中键入也触发键绑定?
我试图在一个带有拆分窗格的JFrame中实现热键,其中一个窗格上有一个JTree。键绑定工作得很好,除了当用户编辑JTree节点的名称时,如果他们按下具有键绑定的键,则会在文本区域键入击键,并触发键绑定。关于如何允许编辑节点,同时仍然实现热键,有什么想法吗 下面是一个演示该行为的示例。“1”和“2”键是绑定的,因此如果您在文本区域中键入其中一个,您将看到弹出窗口Java 如何防止在文本区域中键入也触发键绑定?,java,swing,jtextarea,key-bindings,Java,Swing,Jtextarea,Key Bindings,我试图在一个带有拆分窗格的JFrame中实现热键,其中一个窗格上有一个JTree。键绑定工作得很好,除了当用户编辑JTree节点的名称时,如果他们按下具有键绑定的键,则会在文本区域键入击键,并触发键绑定。关于如何允许编辑节点,同时仍然实现热键,有什么想法吗 下面是一个演示该行为的示例。“1”和“2”键是绑定的,因此如果您在文本区域中键入其中一个,您将看到弹出窗口 import java.awt.BorderLayout; import java.awt.event.ActionEvent; im
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class KeyBindingTest {
static JButton button1;
static JButton button2;
static JPanel panel;
public KeyBindingTest() {
panel = new JPanel(new BorderLayout());
JToolBar tb = new JToolBar();
tb.setFloatable(false);
button1 = new JButton("First Button");
button1.addActionListener(new ButtonAction());
button2 = new JButton("Second Button");
button2.addActionListener(new ButtonAction());
tb.add(button1);
tb.add(button2);
panel.add(tb, BorderLayout.PAGE_START);
JTextArea ta = new JTextArea(10, 30);
JScrollPane opts = new JScrollPane(ta);
panel.add(opts, BorderLayout.PAGE_END);
setKeyBindings(tb);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
KeyBindingTest test = new KeyBindingTest();
test.createAndShowUI();
}
});
}
private void setKeyBindings(JToolBar tb) {
tb.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_1, 0), "first");
tb.getActionMap().put("first", new ButtonAction());
tb.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_2, 0), "second");
tb.getActionMap().put("second", new ButtonAction());
}
private void createAndShowUI() {
JFrame frame = new JFrame();
frame.getRootPane().setDefaultButton(button1);
frame.setLayout(new BorderLayout());
frame.add(panel, BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public class ButtonAction extends AbstractAction {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(panel, "You pressed a button \n" + e.paramString());
}
}
}
我已经有一段时间没有完成Swing了,但我认为可以对ActionEvent调用consume(),以防止它传递给其他侦听器。也就是说,如果在击键击中其他侦听器之前调用consume,则可以防止数字显示在字段中 澄清:
public class ButtonAction extends AbstractAction
{
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e)
{
JOptionPane.showMessageDialog(panel, "You pressed a button \n"+e.paramString());
e.consume();
}
}
您可能需要考虑侦听器的顺序(就像我说的,已经有一段时间了)。我已经有一段时间没有执行Swing了,但是我认为您可以在ActionEvent上调用consume(),以防止它被传递给其他侦听器。也就是说,如果在击键击中其他侦听器之前调用consume,则可以防止数字显示在字段中 澄清:
public class ButtonAction extends AbstractAction
{
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e)
{
JOptionPane.showMessageDialog(panel, "You pressed a button \n"+e.paramString());
e.consume();
}
}
不过,您可能需要考虑侦听器的顺序(就像我说的,已经有一段时间了)。这就是为什么热键通常有Alt或Control修饰符的原因 您可以修改操作以确定哪个组件具有焦点:
@Override
public void actionPerformed(ActionEvent e)
{
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
Component focusedComponent = kfm.getFocusOwner();
if (focusedComponent instanceof JTextArea)
return;
JOptionPane.showMessageDialog(panel, "You pressed a button \n"+e.paramString());
}
这就是热键通常具有Alt或Control修饰符的原因 您可以修改操作以确定哪个组件具有焦点:
@Override
public void actionPerformed(ActionEvent e)
{
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
Component focusedComponent = kfm.getFocusOwner();
if (focusedComponent instanceof JTextArea)
return;
JOptionPane.showMessageDialog(panel, "You pressed a button \n"+e.paramString());
}
非常感谢。我想到了,但是ActionEvent上没有consume(),这是怎么回事?ActionEvent继承自awteEvent,这是consume()方法的来源。请参阅例如。(抱歉;错误链接。修复。)如果consume不可用,您可以尝试向节点添加一个击键侦听器,以在用户键入数字1或2时撤消对其的添加。它显然不可见。我想我看到了它是受保护的,但我不记得我现在在哪里看到的。不能保证1-他们的操作会在其他人之前被调用,2-调度器会检查事件的状态,
KeyListener
因为忽略它而臭名昭著谢谢!我想到了,但是ActionEvent上没有consume(),这是怎么回事?ActionEvent继承自awteEvent,这是consume()方法的来源。请参阅例如。(抱歉;错误链接。修复。)如果consume不可用,您可以尝试向节点添加一个击键侦听器,以在用户键入数字1或2时撤消对其的添加。它显然不可见。我想我看到了它是受保护的,但我不记得我现在在哪里看到的。不能保证1-它们的操作将在其他操作之前被调用,2-调度器将检查事件的状态,KeyListener
因忽略它而臭名昭著。我可以接受的答案大多是,“不要按你现在的方式做。”:)谢谢。我可以接受的答案是,“不要用你现在的方式去做。”:)