Reputation: 237
I have a MIDI piano program that triggers a note to be played when either the mouse is clicked on the note, or a particular keyboard key is typed. I'd like the keyPressed
event to behave the same way the mousePressed
event does, triggering the note to be played once while the key is being pressed.
However, it keeps playing the note over and over while the key is still pressed. I've looked at some threads regarding this topic but I still don't know how to solve the problem (I didn't fully understand how I could apply the other approaches).
Here's the keyPressed
code I have now:
@Override
public void keyPressed(KeyEvent ke) {
if(ke.getKeyCode() == KeyEvent.VK_Z)
{
channel.noteOn (((WhiteKey) WhiteKeys[0]).getNote (), 127);
}
else if(ke.getKeyCode() == KeyEvent.VK_X)
{
channel.noteOn (((WhiteKey) WhiteKeys[1]).getNote (), 127);
}
else if(ke.getKeyCode() == KeyEvent.VK_C)
{
channel.noteOn (((WhiteKey) WhiteKeys[2]).getNote (), 127);
}
else if(ke.getKeyCode() == KeyEvent.VK_V)
{
channel.noteOn (((WhiteKey) WhiteKeys[3]).getNote (), 127);
}
else if(ke.getKeyCode() == KeyEvent.VK_B)
{
channel.noteOn (((WhiteKey) WhiteKeys[4]).getNote (), 127);
}
else if(ke.getKeyCode() == KeyEvent.VK_N)
{
channel.noteOn (((WhiteKey) WhiteKeys[5]).getNote (), 127);
}
else if(ke.getKeyCode() == KeyEvent.VK_M)
{
channel.noteOn (((WhiteKey) WhiteKeys[6]).getNote (), 127);
}
else if(ke.getKeyCode() == KeyEvent.VK_COMMA)
{
channel.noteOn (((WhiteKey) WhiteKeys[7]).getNote (), 127);
}
else if(ke.getKeyCode() == KeyEvent.VK_PERIOD)
{
channel.noteOn (((WhiteKey) WhiteKeys[8]).getNote (), 127);
}
else if(ke.getKeyCode() == KeyEvent.VK_SLASH)
{
channel.noteOn (((WhiteKey) WhiteKeys[9]).getNote (), 127);
}
else if(ke.getKeyCode() == KeyEvent.VK_S)
{
channel.noteOn (((BlackKey) BlackKeys[0]).getNote (), 127);
}
else if(ke.getKeyCode() == KeyEvent.VK_D)
{
channel.noteOn (((BlackKey) BlackKeys[1]).getNote (), 127);
}
else if(ke.getKeyCode() == KeyEvent.VK_G)
{
channel.noteOn (((BlackKey) BlackKeys[2]).getNote (), 127);
}
else if(ke.getKeyCode() == KeyEvent.VK_H)
{
channel.noteOn (((BlackKey) BlackKeys[3]).getNote (), 127);
}
else if(ke.getKeyCode() == KeyEvent.VK_J)
{
channel.noteOn (((BlackKey) BlackKeys[4]).getNote (), 127);
}
else if(ke.getKeyCode() == KeyEvent.VK_L)
{
channel.noteOn (((BlackKey) BlackKeys[5]).getNote (), 127);
}
else if(ke.getKeyCode() == KeyEvent.VK_SEMICOLON)
{
channel.noteOn (((BlackKey) BlackKeys[6]).getNote (), 127);
}
}
Upvotes: 1
Views: 4031
Reputation: 163
I couldn't find an event that will fire once when the key is pressed. However you could use a boolean that will be set when the key is pressed and only resets when the key is released. Then you can play the midi tune only while the boolean is false, which will be only once per keystroke.
boolean zPressed = false;
public void keyPressed(KeyEvent ke) {
if(ke.getKeyCode() == KeyEvent.VK_Z)
{
if (!zPressed) {
channel.noteOn (((WhiteKey) WhiteKeys[0]).getNote (), 127);
zPressed = true;
}
}
}
public void keyReleased(KeyEvent ke) {
if(ke.getKeyCode() == KeyEvent.VK_Z)
{
zPressed = false;
}
Upvotes: 1