|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: INNER | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object | +--java.awt.Component | +--java.awt.Canvas | +--net.groboclown.gui.tripleBuffer.v1.TripleBufferCanvas
Triple buffering of images.
To use in your own applications, create a subclass of the TripleBufferCanvas, implement the method
protected void drawImage( Graphics buffer ), which performs the offscreen drawing to the image img once. To
start the animation thread, use the command [myCanvas].start();
If you need to monitor the screen size, override the method protected void windowChangedSize()
;
the variables width
and height
are set to the proper values. This is only called when
both width
and height
are > 0.
Current important points of interest:
1. does not use Thread.stop() or Thread.suspend(), since JDK1.2 deprecated these. Instead, we supply
interface methods which perform the same task without calling the Thread methods.
2. handles resizing calls
3. subclasses can use the integers width and height to check for the current dimensions. These values are
only changed in resizing calls, and are used by the paint method.
Why this is important:
Standard drawing draws directly to the screen, which can show flickering due to the pauses between each
draw step.
Double buffering is writing to an offscreen image before displaying that image, so that the flicker from
normal drawing doesn't appear.
Double buffering can be inadequate if your image takes a while to draw. Hence, repeated calls to paint()
with a slow drawing routine will reduce the speed of the windowing system as well.
Triple buffering solves this by 1. storing the current image to show, so that any calls to paint() will
display the already created image, 2. drawing the next frame in an offscreen buffer in a separate thread, and
3. synchronizing the paint and draw routines for seamless execution.
It is possible to create a subclass which only draws one image at a time, waiting for an outside source to
signal when to paint another frame. To do this, at the end of your drawImage() routine, call suspend(), which
will pause the execution after the canvas has sent the signal to draw the new image, and all frame skip checking
is completed. Then, in user code when the next frame is ready to be painted, call resume() to draw the
next frame.
Room for improvement:
2. The pause loop in run() should be re-written to do a wait() on a pause object. Needs to be tested
for synchronizing against other threads.
3. Repaint() has been replaced to pass the paint command within 50 millis. This could be adjusted
by users. Also, could use a separate set of variables to specify where in the region to repaint, in case
only a small portion needs to be updated.
Inner classes inherited from class java.awt.Canvas |
Canvas.AccessibleAWTCanvas |
Inner classes inherited from class java.awt.Component |
Component.AccessibleAWTComponent, Component.AWTTreeLock |
Field Summary | |
protected Color |
bgcolor
The drawImage class can modify this at will to change the background color of the drawn image |
private int |
currentIndex
Specify which of the 2 images/graphics is to be painted on the screen. |
private Thread |
drawer
The drawing thread - this class should totally control it. |
private boolean |
drawEveryFrame
Should we wait for each frame to be drawn? |
private int |
drawingIndex
Specify which of the 2 images/graphics is to be drawn to in the background. |
private Graphics[] |
gfx
2 Graphics correlating to the drawing buffers |
protected int |
height
Canvas height, in pixels (<= 0 means we're currently undrawable) |
private Image[] |
img
2 Images for drawing buffers |
private boolean |
isPaused
Thread state flags: is the process paused |
private boolean |
isRunning
Thread state flags: is the process still running |
private int |
repaintCount
|
private int |
waitTime
The time to wait between each drawImage() call, in milliseconds; <= 0 means no wait at all. |
protected int |
width
Canvas width, in pixels (<= 0 means we're currently undrawable) |
Fields inherited from class java.awt.Canvas |
base, nameCounter, serialVersionUID |
Fields inherited from interface java.awt.image.ImageObserver |
ABORT, ALLBITS, ERROR, FRAMEBITS, HEIGHT, PROPERTIES, SOMEBITS, WIDTH |
Constructor Summary | |
TripleBufferCanvas()
Default constructor: do nothing |
Method Summary | |
protected void |
createImages()
creates images to match the current size, and sets up paint so it does not draw the wrong sized image last made. |
abstract void |
drawImage(Graphics img)
user supplied drawing routine. |
void |
finalize()
Quit and cleanup |
int |
getWaitTime()
|
boolean |
isAlive()
|
boolean |
isFrameSkippingAllowed()
|
void |
paint(Graphics g)
draws the currentImg to the screen, if there is an image to draw. |
void |
resume()
pauses the execution of the drawing thread in a safe manner, after the current image has been drawn and repaint() has been called, and waitTime has elapsed. |
void |
run()
Thread execution loop, which synchs with the paint routine to seamlessly and contiuously animate the canvas until stopped or paused. |
void |
setBounds(int x,
int y,
int w,
int h)
Intercepts all resizing calls. |
void |
setFrameSkippingAllowed(boolean allowFrameSkipping)
This routine must be done in a thread-safe way to prevent dead-locking. |
void |
setWaitTime(int millis)
|
void |
start()
Starts the drawing thread. |
void |
stop()
Stops the drawing thread in a safe manner. |
void |
update(Graphics g)
modify the update routine so that there isn't any flicker when we repaint the screen |
protected void |
windowChangedSize()
user supplied routine to capture resizing calls. |
Methods inherited from class java.awt.Canvas |
|
Methods inherited from class java.lang.Object |
clone, equals, getClass, hashCode, notify, notifyAll, registerNatives, wait, wait, wait |
Field Detail |
protected int width
protected int height
protected Color bgcolor
private Image[] img
private Graphics[] gfx
private int currentIndex
private int drawingIndex
private Thread drawer
private boolean isRunning
private boolean isPaused
private int waitTime
private boolean drawEveryFrame
private int repaintCount
Constructor Detail |
public TripleBufferCanvas()
Method Detail |
public abstract void drawImage(Graphics img)
buffer
- the buffer to draw to; when we return this buffer will be sent to paint() for drawing.protected void windowChangedSize()
public void setWaitTime(int millis)
millis
- the (new) time to wait in between each draw, in milliseconds. If is <= 0, then don't wait.public int getWaitTime()
public boolean isFrameSkippingAllowed()
public void setFrameSkippingAllowed(boolean allowFrameSkipping)
allowFrameSkipping
- true = we allow for frames to be skipped if we draw them faster than we paint them,
false = we require that each frame be painted.public boolean isAlive()
public void start()
public void stop()
public void resume()
public void update(Graphics g)
update
in class Component
public void paint(Graphics g)
paint
in class Canvas
public void setBounds(int x, int y, int w, int h)
setBounds
in class Component
protected void createImages()
public final void run()
run
in interface Runnable
public void finalize()
finalize
in class Object
|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: INNER | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |