按下其他键后,JButton键侦听器不会触发

我正在用Java创建一个虚拟钢琴。 到目前为止,我有两个按键的动作监听器,它们大部分都在工作,而不是一个接一个。 例如,我在键盘上点击q然后按下c键并播放ac,这就是它应该做的事情。 但是我想通过按键盘上的w来敲击钢琴上的d键,如果我已经按下q键,它就不会这样做。

 // c key JButton btnC3 = new JButton(""); btnC3.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_Q) { btnC3.doClick(); } } }); btnC3.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { // play c try { keys.playNote(Notes.c3.getValue()); } catch (InterruptedException e1) { e1.printStackTrace(); } catch (InvalidMidiDataException e2) { e2.printStackTrace(); } } }); // d key JButton btnD3 = new JButton(""); btnD3.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_W) { btnD3.doClick(); } } }); btnD3.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { // play d try { keys.playNote(Notes.d3.getValue()); } catch (InterruptedException e1) { e1.printStackTrace(); } catch (InvalidMidiDataException e2) { e2.printStackTrace(); } } }); btnD3.setBackground(Color.WHITE); btnD3.setBounds(wKeyWidth*1, 0, wKeyWidth, wKeyHeight); frame.getContentPane().add(btnD3); 

问题与键盘焦点有关, KeyListener只会在侦听器注册到IS可聚焦和HAS焦点时生成事件。

显然,当“点击”按钮时,它会获得焦点,这意味着其他任何组件都无法响应。

基本答案是,使用Use Key Bindings API 。

您可以做出许多选择,您可以使用当前容器来注册密钥绑定,例如……

 InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW); ActionMap am = getActionMap(); JButton btnC3 = new JButton(""); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, 0), "c3"); am.put("c3", new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { btnC3.doClick(); } }); btnC3.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { // play c try { keys.playNote(Notes.c3.getValue()); } catch (InterruptedException e1) { e1.printStackTrace(); } catch (InvalidMidiDataException e2) { e2.printStackTrace(); } } }); JButton btnD3 = new JButton(""); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "d3"); am.put("d3", new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { btnD3.doClick(); } }); 

或者您可以在各个组件中注册它们。 选择主要取决于您希望解决方案的可重用性。

例如,您可以创建一个可以应用于JButton和键绑定的Action ,这意味着您无需以编程方式单击该按钮。

例如…

 public class NoteAction extends AbstractAction { private Note note; private Keys keys; public NoteAction(Note note, Keys keys) { this.note = note; this.keys = keys; } @Override public void actionPerformed(ActionEvent e) { keys.playNote(note.getValue()); } } 

(我没有你的代码,所以我只是制作一些类名)

然后你可以简单地使用……

 NoteAction noteAction = new NoteAction(Notes.d3, keys); JButton btnC3 = new JButton(noteAction); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, 0), "c3"); am.put("c3", noteAction); 

设置它。

有关详细信息,请参见如何使用操作

重点是问题。 按下q时它会起作用,因为该按钮具有焦点。 如果按下w,无论是否先按q,它都无法工作,因为“q”按钮始终具有焦点。 您应该使用KeyBindings。 尽管任何组件都有重点,它们仍可正

另一个解决方案是将q和w按钮按下添加到添加到JFrame上的keylistener并使用requestFocus()和grabFocus()。

但是您需要为JFrame中的keylistener添加实现,并为按钮按下和释放按钮。

这里有一个完美的链接,可以看到焦点如何影响按键在挥杆时的工作方式

http://www.javaworld.com/article/2076720/core-java/focus-on-swing.html