Can't draw on an Image under OSX

I have an AnimatedAppComponent and an Image where I dynamically draw some lines and other shapes, and I expect it to be printed on screen every time the paint() function is called, at a give frame rate. Some sample code:

 Constructor:
 {
 // BMP is a class member
 BMP = Image(Image::RGB, 320, 240, true);
 
 // myGraphics is a class member
 myGraphics = new Graphics(BMP);
 
 setFramesPerSecond(60);
 }
 
 // A function called by a separate thread:
 void Animate()
 {
     myGraphics->drawSomething()...
     myGraphics->drawSomethingElse()...
     myGraphics->drawSomethingMore()...
 }
 
 void MyClass::paint (Graphics& g)
 {
 	g.setImageResamplingQuality(g.lowResamplingQuality);
 	g.drawImage(BMP, 0, 0, getWidth(), getHeight(), 0, 0, 320, 240);
 }

Under Windows it works as expected. Under OSX (10.14.16) only the first frame is shown, then the BMP object is never modified again. What can be the cause?

The Graphics context is not meant to be kept around. You should create one on the stack and let it go out of scope. Chances are, that the graphics are only flushed once it is destroyed, judging from your observations.

So your example should look like:

Constructor:
 {
 // BMP is a class member
 BMP = Image(Image::RGB, 320, 240, true);
 
 setFramesPerSecond(60);
 }
 
 // A function called by a separate thread:
 void Animate()
 {
     Graphics myGraphics (BMP);
     myGraphics.drawSomething()...
     myGraphics.drawSomethingElse()...
     myGraphics.drawSomethingMore()...
 }
 
 void MyClass::paint (Graphics& g)
 {
 	g.setImageResamplingQuality(g.lowResamplingQuality);
 	g.drawImage(BMP, 0, 0, getWidth(), getHeight(), 0, 0, 320, 240);
 }

Sorry, was interrupted, to add some more detail:

1.) If Animate is indeed called from a different thread, you need to have some synchronisation mechanism in place, so you don’t access the image from paint and Animate at the same time. The JUCE examples usually use a Timer, which is executed on the message thread, so there is no collision

2.) If your Animate has only trivial drawing methods, it is beneficial to only update the model in that function and call repaint(), leaving all your paint code in paint(). The benefit is, you avoid having to copy the whole image and you only paint, when you have to.

Have also a look at the AnimationDemo in the examples folder

Thank you, Daniel! You are right, using the Graphic element only locally solves the problem on OSX, although I wonder why this wasn’t a problem in Windows.

And you were also right in what you say about using separate threads. I have modified my code so that the animation is updated only when the screen refreshes, it’s faster and safer.

Thanks again.