Canvas Buffering

After spending most of the day checking posts I am still a bit confused. Like many I am slow to the party and will need to upgrade a lot of my old sloppy code removing .graphics refs.

I have a project that works fine in MacOS probably because the buffering is handled for me so even some of my inefficient code looks okay. I have optimised some of the unnecessary redraws to help my windows project. I probably read a bit too far back in the posts but when I read the docs on the DoubleBuffer canvas option I understood it to read if I turned it on and turned off Erasebackground it would smooth things out on Windows but my program redraws slowly and then erases the canvas leaving it blank.

I tried to make a canvas class to do the offscreen drawing but failed here also.

So in need of an example to help me get back on track for the correct way to do a detailed offscreen draw and invalidate the canvas to have the paint event draw it smoothly and quickly. I also played around with Michel’s me.backdrop = buffpic approach but somewhere in the program buff pic keeps resetting to nil??

Small eg would probably send me in the right direction.

Thanks

Simplest description I can imagine:

Right now, you draw to a canvas’s graphics

Canvas1.graphics.dothis
Canvas1.graphics.dothat

The offscreen method draws on a picture instead of the canvas, then shows the picture on demand.

Add a picture property to the window , (or maybe the app, or maybe a module.)
For now, assume it is called OFFSCREEN, and it is a property of the window, and your code is a method of the window

[code]//You need to ensure that OFFSCREEN exists
if OFFSCREEN = nil then
OFFSCREEN = new picture (Canvas1.width,Canvas1.height)
end if

//You need to ensure that it is the right size
if OFFSCREEN.width <> Canvas1.width or OFFSCREEN.height <> Canvas1.height then
OFFSCREEN = new picture (Canvas1.width,Canvas1.height)
end if

//And now, change your old drawing to use OFFSCREEN instead:
//Canvas1.graphics.dothis
//Canvas1.graphics.dothat

OFFSCREEN.graphics.dothis
OFFSCREEN.graphics.dothat

//and finally tell Canvas1 there is something to show
Canvas1.invalidate
[/code]

In the Canvas1.Paint() event , you need to display OFFSCREEN

g.drawpicture OFFSCREEN,0,0

For simplicity, I have avoided discussing HiDPI (mainly because I haven’t caught up with THAT myself yet)

The alternative to the above is to put all the drawing code into the PAINT() event of the canvas.
Now, Im in two minds over that. To me, it seems that a lot of drawing and calculation code could be repeated over and over again if Paint events fire a lot, whereas drawing once to OFFSCREEN means there is not a lot of computation going on if the underlying data doesn’t change often.
The Paint event just shows ‘the last version you drew’ (OFFSCREEN) using one line of code.

Thanks Jeff that clears it up nicely.
What are your thoughts on turning Doublebuffer ON and Erasebackground = False for canvases on Windows?

Does it improve the drawing speed at all?

Negligible.
Double buffer may slow it down a bit, but you need to do a lot of painting to measure ‘how much’
Its more about flicker

Forum for Xojo Programming Language and IDE. Copyright © 2021 Xojo, Inc.