Question about use of Image as a member variable

I’m applying a GlowEffect to some text in a label, for a title in various parts of the editor. This text does not change ever, except colors by a lookAndFeelChange().

Since drawing the GlowEffect is exceedingly slow (draw the text into an image, apply the glow effect on the image etc. and draw the image to screen), I was thinking of having it create the image only the first time as a member variable, and then if it is already created, just copy to screen from thereon.

I subclassed Label for this…

So is this a correct way to use the Image class?

In GlowLabel class declaration:

    Image image;		// a NULL image member variable

Then in the paint() override (simplified with details left out):

void GlowLabel::paint(Graphics& g)
{
	if (image.isNull())
	{
        // replace the NULL image with a real one:
	    image = Image(Image::ARGB, width, height, true);
   	    Graphics tmp (image);
   	    g.saveState();

		// do drawing stuff into image, etc.
		// do glow effect etc.

		g.restoreState();
	}
	// draw to screen
	Rectangle<int> imageRect(width, height);
	g.drawImage(image, imageRect.toFloat());
}

Then, to cause it to recreate the image:

void GlowLabel::lookAndFeelChanged()
{
	// replace with NULL image
	image = Image();
}

It seems to work - I guess I’m concerned with whether I’ll leak memory, or if this “one way” to use the Image class correctly.

You don’t need to manage the image yourself, you can just call setBufferedToImage(true) on the Component using the GlowEffect.

I tried that, It did not seem to work. As far as I could tell, every time I showed the PageController component (multiple tabbed interface) containing the label again, it got a repaint() and would draw the whole thing again. If I set a breakpoint in the glow effect, it still hits every time. I’ll take another look; maybe I did something wrong…

In the meantime, this works; I just want to know if I am setting and clearing the image variable correctly. It’s not a std::unique_ptr so I can’t do a .reset() on it…

Actually, it seems I have a slightly different problem: Every time you change tabs on a TabbedComponent, it sends a lookAndFeelChanged() to the component in the tab, which causes everything to be redrawn and even recreated in some cases… I’m not sure why… I didn’t explicitly change any lookAndFeels…

This is a great example of why having the JUCE source is so helpful. You can trace the lookAndFeelChanged() callback into JUCE to see why is causing it. :slight_smile:

Yes, that’s what I did. The TabbedComponent calls a lookAndFeelChange everytime you change the tab (which gets propagated to every component and child). Apparently, that is so that it will refresh components that may have had their LAF changed since the last time they were shown.

However, it does mean that without some gymnastics, setBufferedToImage(true) is not going to do anything, since it gets force-repainted.

1 Like

Yeah if the component in question is being shown/hidden then JUCE’s image buffering mechanism won’t work so well in your case.

To answer your original question though: yes, that seems like the correct approach to using images. Personally I would put the code to render to the image in a separate method to make your paint() function a little cleaner.

1 Like

Thanks for the confirmation.