How are Drawables used for Drawable Button?

here’s my code:

Drawable* normalImage;
    Image image = Image(Image::PixelFormat::RGB, polarityButton.getWidth(), polarityButton.getHeight(), true);
    Graphics g{ image };

    g.fillAll(Colours::yellow);

    normalImage->drawAt(g, 0, 0, 1.f);

    polarityButton.setImages(normalImage);

my idea was… i create an image, i draw on that image with a graphics object, i put that graphics object in the Drawable, and then just tell my DrawableButton that’s how it should look.

but when i try to run this it throws a read access exception:

explicit operator bool() const noexcept {
        return static_cast<bool>(_Mypair._Myval2);
    }

read access? does that mean that it trys to read from a point where it doesn’t have the rights to? but what does that have to do with this whole Drawable-stuff?

Drawable* normalImage;
//snip
normalImage->drawAt(g, 0, 0, 1.f);  // this is going to crash

you never initialized normalImage to point to a valid object

that’s because just writing Drawable normalImage is not allowed somehow.
edit: from my understanding i need a bunch of drawable-objects to declare how my buttons should look in different states. so all i’m trying to do is draw on a drawable, but i don’t even get so far, and i can’t even find a single tutorial or resource where anyone ever tried to make a drawableButton without getting all fancy.
most forum topics about drawables start at the point where the people already have their drawables working and ask about less trivial things like bounds. but i can’t even use my method yet… not even sure what’s working about it and what isn’t.

Add one of these as a member to your class. Provide the appropriate constructor arguments, which are commented out currently.

DrawableButton drawableButton { /*const String &buttonName*/, /*ButtonStyle buttonStyle*/ };

Then in your class’s constructor, before you addAndMakeVisible(drawableButton); make several DrawableImage instances, populated with your images.

https://docs.juce.com/develop/classDrawableImage.html

then call this member function on your drawable with the address of all of your images:
https://docs.juce.com/develop/classDrawableButton.html#a234fdfb0b05c4b2fe42b22366377829a

void DrawableButton::setImages	(	const Drawable * 	normalImage,
                                    const Drawable * 	overImage = nullptr,
                                    const Drawable * 	downImage = nullptr,
                                    const Drawable * 	disabledImage = nullptr,
                                    const Drawable * 	normalImageOn = nullptr,
                                    const Drawable * 	overImageOn = nullptr,
                                    const Drawable * 	downImageOn = nullptr,
                                    const Drawable * 	disabledImageOn = nullptr 
                                    )	

https://docs.juce.com/develop/classDrawableImage.html

DrawableImage normalImage; 
normalImage.setImage(...); //set it to your image from disk or wherever
drawableButton.setImages( &normalImage );

Don’t forget to resize your drawableButton correctly in your class’s resized() function

now my code looks like this:

DrawableImage normalImage;
    Image image = Image(Image::PixelFormat::ARGB, polarityButton.getWidth(), polarityButton.getHeight(), true);
    Graphics g{ image };

    g.fillAll(Colours::yellow);

    normalImage.draw(g, 1.f);

    polarityButton.setImages(&normalImage);

it is in the constructor before addAndMakeVisible and also before setSize().

running it brings me to the following exception:

ImagePixelData::ImagePixelData (Image::PixelFormat format, int w, int h)
    : pixelFormat (format), width (w), height (h)
{
    jassert (format == Image::RGB || format == Image::ARGB || format == Image::SingleChannel);
    jassert (w > 0 && h > 0); // It's illegal to create a zero-sized image!
}

even thought the expected behaviour is that it draws a yellow rectangle of the bounds that i have set in the image

edit: oh ofc. the resized comes after this so it doesn’t have bounds yet… yeah^^ brain fart… but still… when i put numbers into the bounds and run the programm no state of the button is a yellow rectangle… it’s just either transparent or has the typical juce background colour if toggleOn. it seems normalImage doesn’t have changed anything about it

Does your polarity button have any bounds? Probably not since you haven’t called resized() yet, which presumably will resize all of your child components…

edit: re-read what you wrote.

Ok so skip your buttons for now.
load your images, and try drawing them in paint via the plain old g.drawImage(...) way of drawing images.

Once you get that working, you’ll know your images are fine, and can proceed with figuring out how to load them into your DrawableButton.

i should add that i use setClickingToggleState(true) on this button.

when i just tried to turn this to false it never draws a button when being clicked. so is it save to assume that now everything is working and i just have to draw all the states?

actually i’m drawing all things from pure code. no images… but i thought i need a DrawableButton because every button in my plugin should look a little different

you could easily define a LookAndFeel for each button:

struct MyButtonA : Button, LookAndFeel_V4
{
    MyButtonA() { setLookAndFeel(this); }
    ~MyButtonA() { setLookAndFeel(nullptr); }
    void paintButton( /*whatever the look and feel args are */ )
    {
        //customize your button's look here.
    }
};

Then just use those instead of this Drawable stuff…

2 Likes

hmmmm… damn… that sounds much more reasonable than what i’m currently trying to do… because i already had one button working perfectly fine as toggleButton but then ran into problems when i tried to make another button due to the drawButton-method not being able to draw 2 buttons differently depending on the button’s name

edit: yeah good idea! i will move “learning drawables” a little back in my to do list of juce things to learn and rather get stuff done now finally. thx!