HitTest?


#1

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? 


#2

If you read the instructions for hitTest, it tells you never to call it directly. Use contains() instead.


#3

 did that.  Same results. 


#4
(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!!


#5

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

#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.