按下其他键后,JButton键侦听器不会触发 [英] JButton Key listener not firing after other key is pressed
问题描述
我正在用Java创建一个虚拟钢琴。到目前为止,我有两个按键的动作监听器,它们大部分工作,而不是一个接一个。例如,我在键盘上点击 q
并按下 c
键并播放ac,这就是它的假设去做。但是我想通过在键盘上点击 w
来点击钢琴上的d键,如果我已经击中了<$ c $,它就不会这样做c> q 键。
I am creating a virtual piano in Java. So far I have action listeners for two of the keys which work for the most part, just not after one another. For example, I hit q
on the keyboard and it presses the c
key and plays a c, which is what it's supposed to do. But then I want to hit the d key on the piano by hitting w
on the keyboard, and it won't do it if I've already hit the q
key.
// 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焦点的组件时生成事件。
The problem is related to key board focus, a KeyListener
will only generate events when the component the listener is registered to IS focusable and HAS focus.
显然,当a按钮被点击它获得焦点,这意味着其他任何组件都无法响应。
Obviously, when a button is "clicked" it gains focus, meaning that none of the other components can responds.
基本答案是,使用的是使用密钥绑定API 。
The basic answer is, use is the Use Key Bindings API.
那里您可以做出多种选择,您可以使用当前容器来注册密钥绑定,例如......
There are a number of choices you can make, you can use the current container to register the key bindings against, for example...
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();
}
});
或者您可以在各个组件中注册它们。选择主要取决于您希望解决方案的可重用性。
or you can register them against in the individual components. The choice will mostly come down to how reusable you want the solution to be.
例如,您可以创建一个 Action
可以应用于 JButton
和键绑定,这意味着您无需以编程方式单击该按钮。
For example, you could create a Action
which can be applied to both the JButton
and key binding which means you don't need to programmatically click the button.
例如......
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());
}
}
(我不是我有你的代码,所以我只是制作一些类名。
然后你可以简单地使用......
Then you could simply use...
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);
进行设置。
参见如何使用操作了解更多详情
这篇关于按下其他键后,JButton键侦听器不会触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!