I have this code to draw key presses, and it is working fine. I am triggering the repaint ONLY when a key is pressed or released(atleast I think I am), but the paint method is being called continuously for any key that is left pressed(but not being repainted continuously when no key is pressed), from where is the repaint being triggered?
bool Piano::OverlayKeyPaint::keyPressed(const juce::KeyPress& k, juce::Component* c) {
int code = k.getKeyCode();
int keyCode = KeysAndCorrespondingKeyCodes[code];
if (keyCode != -1) {
this->pressedWhiteKeyCodes.insert(code);
WhiteKeyDown(keyCode);// this method triggers paint()
return true;
} else if (BlackKeysAndCorrespondingKeyCodes[code] != -1) {
this->pressedBlackKeyCodes.insert(code);
BlackKeyDown(BlackKeysAndCorrespondingKeyCodes[code]);// this method triggers paint()
return true;
}
return false;
}
bool Piano::OverlayKeyPaint::keyStateChanged(bool isKeyDown, juce::Component* c) {
int num = 0;
for (auto i = pressedWhiteKeyCodes.begin(); i != pressedWhiteKeyCodes.end(); i++) {
if (!juce::KeyPress::isKeyCurrentlyDown(*i)) {
WhitePressedTemp.push(*i);num ++;
WhiteKeyUp(KeysAndCorrespondingKeyCodes[*i]);// this method triggers paint()
}
}
while(!WhitePressedTemp.empty()) {
pressedWhiteKeyCodes.erase(WhitePressedTemp.front()); WhitePressedTemp.pop();
}
for (auto i = pressedBlackKeyCodes.begin(); i != pressedBlackKeyCodes.end(); i++) {
if (!juce::KeyPress::isKeyCurrentlyDown(*i)) {
BlackPressedTemp.push(*i);num ++;
BlackKeyUp(BlackKeysAndCorrespondingKeyCodes[*i]);// this method triggers paint()
}
}
while(!BlackPressedTemp.empty()) {
pressedBlackKeyCodes.erase(WhitePressedTemp.front()); BlackPressedTemp.pop();
}
return false;
};
Can anyone tell me where are the extra continuous triggers are coming from ? and how to stop them from triggering the paint() method?
Probably the OS is sending continuous keydown messages to JUCE when a key is held (think about what happens if you hold down a key in a text editor).
It looks like you are already storing which keys are down and which are not, using perhaps std::set ( pressedWhiteKeyCodes and pressedBlackKeyCodes). So you could only repaint if the key code is not already pressed. Or (probably easier) you could just do a simple if in WhiteKeyUp and BlackKeyUp to not repaint if the state hasn’t changed.
Thanks for the reply!!, That is exactly what is happening. In fact both the KeyPressed and KeyStateChanged are being continuously triggered when the key is down, problem fixed. here is the final code :
bool Piano::OverlayKeyPaint::keyPressed(const juce::KeyPress& k, juce::Component* c) {
int code = k.getKeyCode();
int keyCode = KeysAndCorrespondingKeyCodes[code];
if (keyCode != -1 && (this->pressedWhiteKeyCodes.find(code) == this->pressedWhiteKeyCodes.end())) {
this->pressedWhiteKeyCodes.insert(code);
WhiteKeyDown(keyCode);
repaint();
return true;
}
if (BlackKeysAndCorrespondingKeyCodes[code] != -1 && (this->pressedBlackKeyCodes.find(code) == this->pressedBlackKeyCodes.end())) {
this->pressedBlackKeyCodes.insert(code);
BlackKeyDown(BlackKeysAndCorrespondingKeyCodes[code]);
repaint();
return true;
}
return false;
}
std::queue<int> WhitePressedTemp;
std::queue<int> BlackPressedTemp;
bool Piano::OverlayKeyPaint::keyStateChanged(bool isKeyDown, juce::Component* c) {
bool stateChange = false;
for (auto i = pressedWhiteKeyCodes.begin(); i != pressedWhiteKeyCodes.end(); i++) {
if (!juce::KeyPress::isKeyCurrentlyDown(*i)) {
WhitePressedTemp.push(*i);
WhiteKeyUp(KeysAndCorrespondingKeyCodes[*i]);
}
}
while(!WhitePressedTemp.empty()) {
pressedWhiteKeyCodes.erase(WhitePressedTemp.front()); WhitePressedTemp.pop();stateChange = true;
}
for (auto i = pressedBlackKeyCodes.begin(); i != pressedBlackKeyCodes.end(); i++) {
if (!juce::KeyPress::isKeyCurrentlyDown(*i)) {
BlackPressedTemp.push(*i);
BlackKeyUp(BlackKeysAndCorrespondingKeyCodes[*i]);
}
}
while(!BlackPressedTemp.empty()) {
pressedBlackKeyCodes.erase(BlackPressedTemp.front()); BlackPressedTemp.pop();stateChange = true;
}
if (stateChange) repaint();
return false;
};
the keyPressed method is used to tell the component system if the component has consumed the key event. for example you could return false if the length from the center to min(width, height) is smaller than the length from the center to the mouse position to make a round hitbox.
you probably want to override the mouse functions:
mouseDown
mouseDrag
mouseUp
mouseDoubleClick
mouseWheelMove
mouseEnter
mouseExit
to define your component’s mouse behaviour in regard to mouse (and some key) events