Search code examples
c++user-interfacemouseeventjuce

Juce c++ - mouse events don't work


I just started using Juce GUI library for c++. I am trying to create custom listbox where I will display file names later. Now I need to change the background color of the rows of this custom listbox when mouse is in/out/clicked. The problem is that MouseEnter(), MouseExit() and MouseUp() don't work. Here is the code:

class LeftExplorerItem : public Component, public MouseListener {

public:

LeftExplorerItem(String name = "LeftExplorerItem") : Component(name), isActive(false) {

    setSize(100, 20);

    addMouseListener(this, true);

}

void paint(Graphics& g) override {

    if (!isActive) g.setColour(Colour(40, 40, 40));
    else g.setColour(Colour(150, 190, 255));
    g.fillRoundedRectangle(2, 2, getWidth() - 4, getHeight() - 4, 4);



    g.setColour(Colours::white);
    g.drawText("Frame #", 40, 0, 100, 25, Justification::centredLeft);



}

void mouseEnter(const MouseEvent& event) override {
    AlertWindow("", "", AlertWindow::AlertIconType::InfoIcon);
    isActive = true;

}

void mouseExit(const MouseEvent& event) override {

    isActive = false;

}

void mouseUp(const MouseEvent& event) override {
    AlertWindow("", "click", AlertWindow::AlertIconType::InfoIcon);
}

void resized() override {

}

private:

bool isActive;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LeftExplorerItem)
};

This is just the class for each item of my custom listbox. Keep in mind that everything appears okay (listbox, all listbox items, etc) the only problem is that mouse events never get triggered. What is missing here?


Solution

  • You don't need to derive from MouseListener here -- the Component class has its own built-in version of all the mouse update methods, all of which have the same signature as those in the MouseListener class. Either

    a) remove the derivation from MouseListener and don't add a mouse listener to the component. Things should just work.

    class LeftExplorerItem : public Component /*, public MouseListener*/ {
    
    public:
    
    LeftExplorerItem(String name = "LeftExplorerItem") : Component(name), isActive(false) {
    
        setSize(100, 20);
    
        // addMouseListener(this, true);
    
    }
    

    b) Create a separate class that's derived from MouseListener to add the logic you want, and pass a pointer to an object of that type to the addMouseListener method (but this is probably not what you want).

    The docs say that the purpose of a MouseListener class is "If you need to get informed about mouse events in a component but can't or don't want to override its methods, you can attach any number of listeners to the component, and these will get told about the events in addition to the component's own callbacks being called." Sounds to me like multiple inheritance is needlessly getting in your way here.

    Edit: This version of your class changes color when the mouse enters/exits:

    class LeftExplorerItem    : public Component
    {
    public:
        LeftExplorerItem(String name = "LeftExplorerItem") : Component(name), isActive(false) {
    
            setSize(100, 20);
    
            //addMouseListener(this, true);
    
        }
    
        ~LeftExplorerItem()
        {
        }
    
        void paint (Graphics& g) override
        {
            if (!isActive) g.setColour(Colour(40, 40, 40));
            else g.setColour(Colour(150, 190, 255));
            g.fillRoundedRectangle(2, 2, getWidth() - 4, getHeight() - 4, 4);
    
    
    
            g.setColour(Colours::white);
            g.drawText("Frame #", 40, 0, 100, 25, Justification::centredLeft);
    
        }
    
        void resized() override
        {
            // This method is where you should set the bounds of any child
            // components that your component contains..
    
        }
    
        void mouseEnter(const MouseEvent& event) override {
            //AlertWindow("", "", AlertWindow::AlertIconType::InfoIcon);
            isActive = true;
            repaint();
    
        }
    
        void mouseExit(const MouseEvent& event) override {
    
            isActive = false;
            repaint();
        }
    
        void mouseUp(const MouseEvent& event) override {
            //AlertWindow("", "click", AlertWindow::AlertIconType::InfoIcon);
            repaint();
        }
    
    
    private:
    
        bool isActive;
        JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LeftExplorerItem)
    };