2016-05-01 29 views
1

我正在用Java创建虚拟钢琴。到目前为止,我有两个大部分工作的键的动作监听器,而不是一个接一个地工作。例如,我在键盘上点击q,并按下c键并播放一个c,这就是它应该做的。但之后我想通过键盘上的w击打钢琴上的d键,如果我已经击中了q键,它就不会这样做。JButton键监听器在按下其他键之后不会触发

// 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); 
+0

键绑定是您最干净的解决方案。 [例如](http://stackoverflow.com/questions/8087536/keylistener-on-jpanel-randomly-unresponsive/8087810#8087810)。 –

+0

[例如](http://stackoverflow.com/questions/27283908/java-jbutton-keylistener/27284080#27284080)和[示例](http://stackoverflow.com/questions/25073094/jbutton-does-not - 改变颜色 - 当按钮是键入/ 25073230#25073230) – MadProgrammer

回答

1

的问题与键盘焦点,一个KeyListener只会生成事件时,该组件监听者被注册为可聚焦和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(); 
    } 
}); 

,也可以针对各个组件它们注册。选择将主要归结为您想要解决方案的可重用性。

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

例如...

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); 

设置它。

请参阅How to Use Actions了解更多详情

+0

谢谢你的回答。 – Matt

+0

问题,但:我已经把你做的代码,它使我的整个图形用户界面消失。发生这种事情有什么具体原因吗? – Matt

+0

我正在谈论你发布的第一块代码。 – Matt

3

重点是问题所在。当按下q时,它将起作用,因为该按钮具有焦点。无论您先按q,因为“q”按钮始终关注焦点,如果按w,它将无法工作。您应该改用KeyBindings。尽管任何组件都有重点,它们仍然可以工

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

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

这里是完美的链接查看重点是如何影响你的按键放在挥杆是如何工作的

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

+0

谢谢你的回应。我正在调查键绑定。 – Matt

+0

@Matt:这是你的解决方案。 1+ –

+0

[Key Bindings](http://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html)是答案 – MadProgrammer