I have a window containing a canvas and a button. The action for the button contains the following code:
Dim p as New Picture(40,40)
Dim g as Graphics = p.Graphics
g.Pixel(10,10) = RGB(255,0,0) // Draw a red dot
g.Pixel(20,10) = RGB(0,255,0) // Draw a green dot
g.Pixel(30,10) = RGB(0,0,255) // Draw a blue dot
The result I expect is:
Clear the canvas
Draw a red dot
Sleep for 2 seconds
Draw a green dot
Sleep for 2 seconds
Draw a blue dot
What actually happens is:
Clears the canvas
Sleeps for 4 seconds
Draws the red, green and blue dots all at the same time.
In other words it seems to do all the sleeps first and then it does everything else.
Is there a way to make the sleeps and graphics updates happen in the intended order?
Note: This is my first attempt at coding with Xojo.
I’m running this on a Mac with OSX Mountain Lion.
Here are couple of concepts re XOJO and drawing…
- when your application draws into canvas graphics, that is NOT when the visible action gets drawn to screen. In a very very simply app that draws a static image, you get away with it. In your app, you are trying to display a series of different visible states.
Yes, you did draw all three states and your thread did pause, but that doesn’t mean the framework will necessarily update those drawing actions to screen.
You actually should NOT directly access and draw into canvas.graphics. That is of course the natural thing to approach things, and as a XOJO beginner you will be tempted to do things that way. Don’t. If you want to create anything more than trivial static displays, NEVER draw into canvas.graphics. Instead, do all your drawing in response to the canvas’ paint event.
The paint event passes you g as graphics. Draw into the passed g rather than directly manipulating canvas.graphics.
The basic drawing scheme (with your results appearing on screen) is to…
a. canvas.invalidate — to tell the framework you want the canvas redrawn to screen
b. the framework at its next available screen refresh will trigger the canvas.paint event
c. your paint event handler draws into the paint event’s passed g
- Animation is basically done by arranging for a series of invalidates and keeping track of which frame you want to draw for which time epoch. In rough terms, you can set up a timer with a frame counter. At each interval, the timer invalidates the canvas and increments your frame counter.
When the paint event fires, your paint handler checks which frame you want to draw. You then know which animation frame to draw.
This is a rough outline of how to do things, but if you do all your drawing via the paint event, you naturally take care of…
- Refreshing the screen in response to anything covering or uncovering your canvas.
- Updating your animations in a visible manner
- Avoid locking up your apps’s GUI response.
Hope that helps.
Do not use Canvas1.Graphics. Use the Paint EventHandler of Canvas1
Look at “DrawingWithThreads” in the Xojo/Example Projects/Graphics and Multimedia/
In case it isn’t clear. When you invalidate your canvas, your method typically needs to end. That allows the framework to execute the canvas paint and refresh to screen.
If you do your canvas invalidate in a timer, execution of the framework continues when the timer completes its current action.
Thanks for the help. I have solved the problem by using timers rather than sleeps.