Button can't be initialized

When i try to make a Button in my current project its name gives an error called: “juce::Button::paintButton is a pure virtual function”. i made my own lookAndFeel so i thought “ok, maybe i need to override this method first to make buttons work.” so i’ve put this in my lookAndFeel-class:

void paintButton(Graphics& g,
        bool shouldDrawButtonAsHighlighted,
        bool shouldDrawButtonAsDown) override {

    }

i also tried writing Button:: between void and the title but it seems it just doesn’t belong there. then i also tried to copy it in the header-file where i also try to initialize the button, same result. now i’m kinda out of ideas. what am i missing here?

Seems like you need some basic lesson in C++ inheritance to understand what the compiler wants to tell you – here we go! :slight_smile:

Many JUCE classes use the concept of inheritance. In case you don’t know about it here is a brief introduction, focused on virtual functions you seem to have struggles with. However I’d strongly suggest you to have a deeper read on that topic, because it’s a core feature of C++.

You can declare the following class

class Base
{
public:
    // The constructor does nothing more than assigning the value
    Base (int initialValue) : someValue (initialValue) {}

    // a "normal" member function
    int getValue() { return someValue; }

    // A virtual function which defines a basic behaviour. A class inheriting from Base can
    // decide if it wants to use this version or override it.
    virtual void increaseValue() { ++someValue; }
    
    // A pure virtual function (marked by the =0) which defines no behaviour. A class inheriting from 
    // Base has to override it in order to become a usable class
    virtual void printValue() = 0;
    
private:
    int someValue;
}

As the comments state, Base has three member functions but at this time trying to instantiate an instance of Base in your code like declaring Base myBase somewhere will lead to a compile error like Base::printValue is a pure virtual function – just like you got. Why is that the case? Well because printValue is pure virtual, this means the compiler only knows that each class inheriting from Base has a function printValue but Base doesn’t deliver any functionality for printValue. What we have to do to make use of it is to create a new class inheriting from Base that defines some behaviour for that virtual function. This could look like this:

class Inherited1 : public Base // this tells that Inherited1 should have the same public interface as Base
{
    public:
    // As the constructor of Base requires a parameter, we must supply one to the base class. Let's
    // just pass on a value given to the inherited constructor for now
    Inherited1 (int initialValue) : Base (initialValue) {};

    // Here we override the pure virtual function. Inherited1 can now be instantiated in your code as 
    // every member function is defined through either the base class or the inheriting class.
    // Note that we can also use a function of base here (getValue) that still has the same function
    // as declared in the base class
    void printValue() override { std::cout << "Value from Inherited1 instance: " << getValue() << std::endl; }
}

But we could also override the other virtual member function if we wanted to:

class Inherited2 : public Base
{
    public:
    // This constructor just passes the double value passed in to the base constructor
    Inherited2 (int initialValue) : Base (2 * initialValue) {};
    
    // This class decides to multiply the internal value by 2 when increasing it
    void increaseValue() override { someValue *= 2; }

    void printValue() override { std::cout << "Value from Inherited2 instance: " << getValue() << std::endl; }
}

Now you can write this code:

int main()
{
    Inherited1 i1 (0);
    Inherited2 i2 (1);

    i1.printValue(); // should output: Value from Inherited1 instance: 0
    i2.printValue(); // should output: Value from Inherited2 instance: 2

    // Now we can do something fancy: While we can't instantiate a Base object,
    // we can declare both, references and pointers of the type Base and let them 
    // point to inherited instances
    Base& b1 = i1; // This reference now references i1
    Base* b2 = &i2; // This pointer now points to the memory address of i2

    // Ase increaseValue and printValue were declared in the base class, we can call 
    // them on the Base class reference/pointer:
    b1.increaseValue();
    b2->increseValue();
    b1.printValue();  // should output: Value from Inherited1 instance: 1
    b2->printValue(); // should output: Value from Inherited2 instance: 4
}

What is handy with this approach, is that you can now write functions that take a reference or pointer to Base as argument and call their functions and let the object passed in decide what happens when calling them.

4 Likes

Now back to your actual problem:

Looking at the docs/code of Button, we see that the protected function paintButton is marked pure virtual. Why? Because Button is a base class, defining a behaviour general buttons have, but there are lots of different looking button types out there that implement the paint function differently to create a unique look.

So your conclusion:

Is basically right – if you wanted to create a totally unique type of button, by creating a new button class which inherits Button and overrides the method. Adding it to your LookAndFeel is not the right thing, unfortunately :wink:

However I doubt that you want to create a new type of button, most likely you are looking for a simple TextButton – am I right? TextButton overrides this function for you and gives you a usual button with a text on it…

1 Like

thanks for your introduction into inheritance. i actually know about it already since i already overrode functions like the “drawRotarySlider”-one from the lookAndFeel-tutorial. but the fact that Button itself is not definition enough for what kinda button you want, that’s what i was missing. :slight_smile:

idk if i want to create a new type of button, most likely not, yeah :smiley: i just want a polarity switch, so it would have to keep on looking different depending on which mode is currently set. not like a button that only blinks up shortly when it’s pressed, no trigger button, so to say. i would love to have a button-type where i can completely draw this behaviour myself, just like with the drawRotarySlider-method. is TextButton the best option then?

edit: but yeah, you are right that i’m a c++ noob. i’m pretty sure you can tell from how basic my questions sometimes are, lol. but still… it’s incredible that juce even enables me to mostly finish a plugin after just a month of experimentation.

Yeah, I assumed that you had some basic knwoledge as you said somewhere else that you just finished your first plugin – I would have been surprised if you managed to do so without inheriting anything :smile: The reason I went into detail so deep is that think it’s a good thing to explain things from ground up (like the difference between virtual and pure virtual functions), because if you understood it from the ground up, the compiler error is no longer cryptic to you, because it basically just gives you all information you need to understand what has gone wrong. Learning to fully understand compiler errors and warnings is a great motivation in getting really good at writing clean and safe C++ code by the way :slight_smile:

I think I don’t even know each JUCE stock button, especially as I came across many projects that actually use project specific types of Buttons, so looking at all types of buttons could be a good thing to find out what’s already there. What comes to my mind for your use-case would be the DrawableButton that can display different drawables, depending on its toggle state. If your phase inversion icon is a Drawable/SVG, this could be an easy option for you that would not even need any paint customization…

actually yes, i was not aware of the difference. when i saw virtual i just assumed i have to override them all.

the reason why i’m able to finish plugins and ask pretty basic questions at the same time is because i use plug’n script to prototype my dsp ideas, so i can basically just copy it over to a juce header file and change some things to make it compatible. that way i already know my stuff will work more or less perfectly when i compile it. but apart from this huge advantage i am 1000x more lowlevel than 99% here.

that actually isn’t very useful for me right now. i spent a lot of time lately to discover all the shapes you can draw with Graphics& g and wrote and constantly improve my own layout class, which is super fun and i wanna stick to it as much as i can. so it would be best if it was really just a button that lets me draw everything from juce gui objects like rectangles and lines. i will explore textbuttons and drawablebuttons now.