How do you make a Component catch mouse activity?

How do you make a Component in general catch mouse activity?

When you click the mouse onscreen anywhere in your main window, say MainComponent, you can catch mouse events easily. You just override a mouse callback method such as mouseDown or mouseUp–and do the programming. Correct?

However, when you click on a Component onscreen, say Label, those mouse callback methods do not work! The reason is clear: Components follow their own rules when it comes to mouse activity and other things. But… I wish I can associate Label with common mouse events. It should react like the Rectangle in paint() does.

Now, the MouseListener class provides us with an addMouseListener method. That is the one to use, I guess, in order to accomplish this–but I cannot make it work no matter how hard I try. I tried, for instance, to add this to the constructor

addMouseListener(&myLabel, true);

It does not work. Please, help me. Thanks (!)

Greetings, Hugo

You have to add the parent component as a listener. The parent controls all mouse activity, so any children need to be subject to the parent’s mouse methods. (The exception being if you’re using the ValueTree, which handles all mousing unless you explicitly state otherwise.)

After you construct it:

myLabel->addListener(this);

I don’t use Label, as I prefer far more explicit control over the text, but I’m sure the listener method that the Editor then inherits should be fairly obvious, and similar to Button::Listener or Slider::Listener. I imagine it is probably Label::Listener.

Ah. Just so.

In 95% of all use cases, you don’t need to attach mouse listeners at all.
It works, if a mouse event from the OS is sent, JUCE will figure out by traversing the component hierarchy, which component was hit (is under mouse curser, i.e. its hitTest returns true and it has no child that occupies the same space).

If you add now a mouseListener to a component, you are duplicating the event and it’s sent to some other instance. There are use cases for that, but often it leads into a confusing flow IMHO.

You can also get global mouse events, there is Desktop::addGlobalMouseListener(Listener*).
This will catch all mouse events (additionally to the original ones).

If you tell us your actual use case, we can tell you the nicest way to handle that…

Hello Daniel, thanks (!)
What I really want is a Component that
-gives me full control of colors (which Label does),
-full control of text (which Label does),
but also…
-allows me to use the full set of mouse methods,
e.g. those provided by the MouseListener class -> mouseDown, mouseUp, mouseMove, etc.
I can use these methods as callbacks when using a Rectangle object inside paint(), but I cannot do the same with Components. Why is that? That is my problem…
Regards, Hugo

Hello. Mm. I am sorry to say that when I enter
myLabel->addListener(this);
the system red-underlines myLabel and triggers the error “expression must have pointer type”. It does not work…Not even with myLabel& or &myLabel
Hugo.

One thing: every Component (and Label is a Component) is by default mouse listener to itself, so to speak, just that the component is omitted.

To change the Label’s behaviour, when the mouse clicks it, you inherit the Label and override the method:

class MyLabel : public Label
{
public:
    MyLabel() = default;
    void mouseDown (const MouseEvent& event) override
    {
        DBG ("Clicked at: " << event.getPosition().toString());
    }
};

About crandall1’s example, he assumed you were using a pointer like
Label* myLabel; or std_unique_ptr<Label> myLabel; in which case you use the -> operator.
If you have myLabel as member, you use the . operator, so it would read:

myLabel.addListener(this);

Hope that helps

1 Like

Thank you Daniel. This is certainly ‘advanced stuff’ for me–but I will study it carefully, and learn more about C++ details by so doing.

Greetings, Hugo (!)