I have a custom component class with a midiKeyboardComponent added to it. I'm trying to determine if the cursor is within the keyboard. here is how the keyboard's bounds are defined in resized():
int keyHeight = getHeight() * (108.f/180.f);
keyboard->setAvailableRange(21, 21 + 87); //A0 - C8
keyboard->setKeyWidth((DocumentWindow::getWidth() - 3) / 52.f);
keyboard->setBounds(1,
getHeight() - keyHeight,
getWidth() - 2,
keyHeight);
if I hide the keyboard and in paint() draw a rectangle where the keyboard normally goes, it looks like this:
g.setColour(Colours::red);
g.drawRect(keyboard->getBounds());
The bounds of the keyboard are set the way I want them set. it's only occupying part of the window. However, if i perform a hitTest on the keyboard, it returns true as long as the cursor is within my custom class.
void PianoRollView::mouseMove(const juce::MouseEvent &event) {
std::cout << "Cursor within keyboard?: "
<< (keyboard->hitTest(event.x, event.y) ? "true" : "false" )
<< " cursor: "
<< event.x << ", " << event.y
<< " noteAtPosition: "
<< keyboard->getNoteAtPosition(event.getPosition())
<< "\n";;
doAsyncRepaint();
}
you can see the behavior here:
https://youtu.be/6Fd0qBUKFdI
any idea what is causing it?
jules
February 17, 2016, 7:20pm
2
If you read the instructions for hitTest, it tells you never to call it directly. Use contains() instead.
(keyboard->contains(event.getPosition() ) ? "true" : "false" )
always prints "true".
in my resized() method, i printed out the size of the component window as well as the keyboard itself.
std::cout << "pianoRollView Size: "
<< getWidth() << ", " << getHeight()
<< " keyboard size: " << keyboard->getWidth() << ", " << keyboard->getHeight()
<< "\n";
that gives me this output:
pianoRollView Size: 1008, 127 keyboard size: 1008, 76
so I know the keyboard is not the same size vertically as the window it lives in, yet contains() and hitTest() both return true no matter where i place the cursor, be it inside the MidiKeyboardComponent or outside of it. it is really baffling!!
Here's an extremely simple MainContentComponent that demonstrates the behavior:
MainContentcomponent.cpp:
#include "MainComponent.h"
MainContentComponent::MainContentComponent()
{
keyboard = new MidiKeyboardComponent( state.get(), MidiKeyboardComponent::horizontalKeyboard);
addAndMakeVisible(keyboard);
setSize (600, 400);
}
void MainContentComponent::resized()
{
keyboard->setBounds(1, getHeight() * 0.5f, getWidth(), getHeight() * 0.5f );
}
void MainContentComponent::mouseMove(const juce::MouseEvent &event) {
std::cout << (bool)keyboard->contains( event.getPosition() )
<< " " << event.x << " " << event.y
<< "\n";
}
MainContentComponent.h
#ifndef MAINCOMPONENT_H_INCLUDED
#define MAINCOMPONENT_H_INCLUDED
#include "../JuceLibraryCode/JuceHeader.h"
class MainContentComponent : public Component
{
public:
MainContentComponent();
~MainContentComponent() {}
void paint (Graphics&) {}
void resized() {
keyboard->setBounds(1, getHeight() * 0.5f, getWidth(), getHeight() * 0.5f );
}
void mouseMove( const MouseEvent &event )override;
private:
ScopedPointer<MidiKeyboardComponent> keyboard;
SharedResourcePointer<MidiKeyboardState> state;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
};
#endif // MAINCOMPONENT_H_INCLUDED
jules
February 18, 2016, 8:02am
6
You need to read the comments for these component methods more carefully!
contains() takes a local point, relative to its own top-left, not its parent's origin.