public class TLcdGXYAsynchronousPaintQueue extends Object implements ILcdGXYAsynchronousPaintQueue
ILcdGXYAsynchronousPaintQueue
paints layers asynchronously in a background
thread, using off-screen image buffers.
This paint queue creates an image buffer for each relevant painting mode (bodies, labels, selection,...). It creates this buffer in a paint operation, and then retrieves and reuses it in subsequent paint operations. If the image buffer is up to date, it is composited in the view. If the image buffer is outdated, it may still be used to create a preview that is composited. The image buffer is then updated asynchronously, in the painting thread of this queue.
To reduce memory and compositing overhead, it is recommended to reuse a paint queue for
adjacent layers. A paint queue manager
provides an automatic way of doing this.
Because all layers handled by this paint queue are painted onto the same image
buffer(s), these layers need to be adjacent in their view. In other words,
a synchronous layer or asynchronous layer from another paint queue must not be placed
in between layers handled by this queue. If this happens, some layers may or may not be visible.
As an example, the following is a valid layer ordering:
com.luciad.view.gxy.asynchronous.useVolatileImages
" system property to true
.
To benefit from the acceleration, you need a view without any buffers:
view = new TLcdGXYViewJPanelLightWeight();
view.setCachingMode(DISABLE_CACHING);
Unless stated otherwise, all methods should be called on the Event Dispatch Thread.
TLcdGXYAsynchronousPaintQueueManager
Modifier and Type | Class and Description |
---|---|
static class |
TLcdGXYAsynchronousPaintQueue.InterruptMode
Enumeration of the interrupt modes.
|
Modifier and Type | Field and Description |
---|---|
static int |
BODIES
Asynchronous painting mode constant that specifies to paint only bodies
asynchronously.
|
static int |
BODIES_AND_SKIP
Asynchronous painting mode constant that specifies to paint only bodies
asynchronously.
|
static int |
EVERYTHING
Asynchronous painting mode constant that specifies to paint everything
asynchronously: bodies, labels, selection,...
|
Constructor and Description |
---|
TLcdGXYAsynchronousPaintQueue(ILcdGXYView aView)
This convenience constructor is equivalent with calling
TLcdGXYAsynchronousPaintQueue( ILcdGXYView aView, EVERYTHING, 0, 200, 25 ) |
TLcdGXYAsynchronousPaintQueue(ILcdGXYView aView,
int aPaintMode)
This convenience constructor is equivalent with calling
TLcdGXYAsynchronousPaintQueue( ILcdGXYView aView, int aPaintMode, 0, 200, 25 ) |
TLcdGXYAsynchronousPaintQueue(ILcdGXYView aView,
int aPaintMode,
double aBorderFactor,
int aSkipDelay,
int aSynchronousDelay)
Creates a new asynchronous paint queue for the given view.
|
Modifier and Type | Method and Description |
---|---|
void |
addGXYAsynchronousPaintListener(ILcdGXYAsynchronousPaintListener aListener)
Registers an
ILcdGXYAsynchronousPaintListener to be informed of asynchronous painting events. |
double |
getBorderFactor()
Returns the relative size of the surplus border that is painted.
|
ILcdGXYView |
getGXYAsynchronousView(ILcdGXYAsynchronousLayerWrapper aWrapper,
int aMode,
ILcdGXYView aGXYView)
Returns the view on which the asynchronous paint requests are actually
executed.
|
ILcdGXYView |
getGXYView()
Returns the view for which this painter paints asynchronously.
|
int |
getIntermediateUpdateInterval()
Returns the interval for which to display intermediary updates.
|
TLcdGXYAsynchronousPaintQueue.InterruptMode |
getInterruptMode()
Returns the interrupt mode.
|
int |
getPaintMode()
Returns what modes are painted asynchronously.
|
int |
getPriority()
Returns the current thread priority of the internal painting thread.
|
int |
getSkipDelay()
Returns how long the paint queue should wait before displaying synchronous content (e.g. labels)
again, when they have been omitted in the BODIES_AND_SKIP mode.
|
int |
getSynchronousDelay()
Returns how long
paint(java.awt.Graphics, com.luciad.view.gxy.asynchronous.ILcdGXYAsynchronousLayerWrapper, int, com.luciad.view.gxy.ILcdGXYView) waits for asynchronous paints. |
void |
invokeAndWait(Runnable aRunnable)
Executes the given
Runnable synchronously, but without interfering with the paint thread. |
void |
invokeLater(Runnable aRunnable)
Executes the given
Runnable in the paint thread and returns immediately. |
void |
invokeLaterInEDT(Runnable aRunnable)
Executes the given
Runnable in the event dispatch thread and returns immediately. |
boolean |
isEmpty()
Returns true if the paint queue is not painting and it has no paint requests to finish.
|
boolean |
isInterruptPainting()
Returns true if ongoing paints are stopped when new paints are scheduled.
|
boolean |
isTraceOn()
Deprecated.
This method has been deprecated. It is recommended to use the
standard Java logging framework directly.
|
void |
paint(Graphics aGraphics,
ILcdGXYAsynchronousLayerWrapper aWrapper,
int aMode,
ILcdGXYView aGXYView)
Paints an image of the painted layers using the given graphics.
|
void |
removeGXYAsynchronousPaintListener(ILcdGXYAsynchronousPaintListener aListener)
Stops informing the given
ILcdGXYAsynchronousPaintListener of asynchronous painting events. |
void |
reset()
Clears all cached images and paint requests.
|
void |
setBorderFactor(double aFactor)
Sets the relative size of the surplus border that is painted.
|
static void |
setClassTraceOn(boolean aClassTraceOn)
Deprecated.
This method has been deprecated. It is recommended to use the
standard Java logging framework directly.
|
void |
setIntermediateUpdateInterval(int aInterval)
Sets the interval for which to display intermediary updates.
|
void |
setInterruptMode(TLcdGXYAsynchronousPaintQueue.InterruptMode aInterruptMode)
Sets the interrupt mode.
|
void |
setInterruptPainting(boolean aInterruptPainting)
Determines whether to stop ongoing asynchronous paints when new paints are scheduled.
|
void |
setPriority(int aPriority)
Sets the thread priority to be used by the internal painting thread.
|
void |
setSkipDelay(int aDelay)
Sets how long the paint queue should wait before displaying synchronous content (e.g. labels)
again, when they have been omitted in the BODIES_AND_SKIP mode.
|
void |
setSynchronousDelay(int aSynchronousDelay)
Sets how long
paint(java.awt.Graphics, com.luciad.view.gxy.asynchronous.ILcdGXYAsynchronousLayerWrapper, int, com.luciad.view.gxy.ILcdGXYView) waits for asynchronous paints to complete. |
void |
setTraceOn(boolean aTraceOn)
Deprecated.
This method has been deprecated. It is recommended to use the
standard Java logging framework directly.
|
String |
toString() |
public static final int EVERYTHING
public static final int BODIES
public static final int BODIES_AND_SKIP
public TLcdGXYAsynchronousPaintQueue(ILcdGXYView aView)
TLcdGXYAsynchronousPaintQueue( ILcdGXYView aView, EVERYTHING, 0, 200, 25 )
public TLcdGXYAsynchronousPaintQueue(ILcdGXYView aView, int aPaintMode)
TLcdGXYAsynchronousPaintQueue( ILcdGXYView aView, int aPaintMode, 0, 200, 25 )
public TLcdGXYAsynchronousPaintQueue(ILcdGXYView aView, int aPaintMode, double aBorderFactor, int aSkipDelay, int aSynchronousDelay)
TLcdGXYViewJPanel
,
TLcdGXYViewJPanelLightWeight
, and
TLcdGXYViewBufferedImage
views.
The latter view must be painted in the event dispatch thread.
aPaintMode
is one of the following:
TLcdGXYAsynchronousPaintQueue.EVERYTHING
: everything should be painted asynchronously.
This option has the shortest synchronous delay but consumes the most memory.
TLcdGXYAsynchronousPaintQueue.BODIES
: only the bodies are painted asynchronously. This consumes
only half of the memory but may cause long delays when painting the rest of the layer (such as labels and
selection handles)
TLcdGXYAsynchronousPaintQueue.BODIES_AND_SKIP
: only the bodies are painted asynchronously;
the rest is only drawn after the bodies have been painted. Use this mode if your model only contains bodies or
uses caching. As the previous option, this consumes about half of the memory needed for painting everything
asynchronously.
aView
- the view for which to paint asynchronouslyaPaintMode
- indicates what part of the layers should be painted asynchronouslyaBorderFactor
- if not zero, asynchronously painted images will be larger by aBorderFactor
,
so that small pan and zoom changes still display a full cached image.
For example, a view of 300 by 200 pixels will yield asynchronous images of
300 * ( 1 + aBorderFactor ) by 200 * ( 1 + aBorderFactor ).aSkipDelay
- only for BODIES_AND_SKIP mode. Specifies how long to wait before displaying synchronous content, such as
labels and selections, after skipping them.aSynchronousDelay
- specifies how long paint(java.awt.Graphics, com.luciad.view.gxy.asynchronous.ILcdGXYAsynchronousLayerWrapper, int, com.luciad.view.gxy.ILcdGXYView)
waits for asynchronous paints. If the asynchronous paint
completes within the specified time, the results are immediately painted.public static void setClassTraceOn(boolean aClassTraceOn)
true
then all log messages are recorded, otherwise only
the informative, warning and error messages are recorded.aClassTraceOn
- if true then all log messages are recorded,
otherwise only the informative, warning and error messages are recorded.public void setTraceOn(boolean aTraceOn)
true
or false
as argument automatically turns
off tracing for all other class instances for which
setTraceOn
has not been called.
If the argument is false
then only the informative, warning
and error log messages are recorded.aTraceOn
- if true then all log messages are recorded for this
instance. If false, then only the informative, warning and
error log messages are recorded.public boolean isTraceOn()
true
if tracing is enabled for this class.public ILcdGXYView getGXYView()
public int getPaintMode()
EVERYTHING
, BODIES
or BODIES_AND_SKIP
public double getBorderFactor()
public void setBorderFactor(double aFactor)
aFactor
- the relative amount by which to enlarge the image on each side.public void setIntermediateUpdateInterval(int aInterval)
For example, if the queue is working on an asynchronous paint that takes almost 5 seconds, and the interval is set to 1000 milliseconds, the view will be refreshed at least 4 times to display the paint in progress, and one last time to display the final result.
aInterval
- an interval in milliseconds
specifying a refresh rate for displaying intermediate results on the viewgetIntermediateUpdateInterval()
public int getIntermediateUpdateInterval()
setIntermediateUpdateInterval(int)
public boolean isInterruptPainting()
setInterruptPainting(boolean)
public void setInterruptPainting(boolean aInterruptPainting)
If true, only the most recent asynchronous paint is finished and shown. This ensures a high responsiveness, since the paint queue will paint the most recent image as soon as possible.
Setting this to false makes sure that all asynchronous paints are finished and shown. This is useful when the view is continuously being repainted, and the paint queue wouldn't otherwise get the opportunity to finish any paints.
aInterruptPainting
- true if asynchronous paints must be interruptedisInterruptPainting()
public TLcdGXYAsynchronousPaintQueue.InterruptMode getInterruptMode()
setInterruptMode(com.luciad.view.gxy.asynchronous.TLcdGXYAsynchronousPaintQueue.InterruptMode)
public void setInterruptMode(TLcdGXYAsynchronousPaintQueue.InterruptMode aInterruptMode)
isInterruptPainting()
should return true.
By default the interrupt mode is InterruptMode.NON_OVERLAPPING_PAINTS_ONLY.
aInterruptMode
- the interrupt mode.setInterruptPainting(boolean)
,
getInterruptMode()
public void paint(Graphics aGraphics, ILcdGXYAsynchronousLayerWrapper aWrapper, int aMode, ILcdGXYView aGXYView)
ILcdGXYAsynchronousPaintQueue
Note that the paint queue is free to decide if it will execute the paint synchronously or asynchronously (e.g. when confronted with unsupported views).
paint
in interface ILcdGXYAsynchronousPaintQueue
aGraphics
- the graphics to use for paintingaWrapper
- the asynchronous layer wrapper that should be paintedaMode
- the mode indicating what should be painted, see ILcdGXYLayer.paint(java.awt.Graphics, int, com.luciad.view.gxy.ILcdGXYView)
.aGXYView
- the view for which the layer should be painted.public void setSkipDelay(int aDelay)
In BODIES_AND_SKIP mode, the paint method does not paint labels and selections if the bodies are still being painted asynchronously. Hence, they are temporarily not displayed. As an example, suppose the delay is set to 500 milliseconds. If, the bodies are painted in, say 750 milliseconds, the labels and selections are displayed together with the newly painted bodies. If, the bodies are painted in, say 50 milliseconds, the labels and selections are only displayed 450 milliseconds after displaying the newly painted bodies. If the latter case would repeat itself rapidly, the labels stay hidden until after the last asynchronous paint. Without delay, the labels would constantly appear and disappear.
aDelay
- how many milliseconds to wait before displaying synchronous content,
after skipping them.getSkipDelay()
public int getSkipDelay()
setSkipDelay(int)
public void setSynchronousDelay(int aSynchronousDelay)
paint(java.awt.Graphics, com.luciad.view.gxy.asynchronous.ILcdGXYAsynchronousLayerWrapper, int, com.luciad.view.gxy.ILcdGXYView)
waits for asynchronous paints to complete.
If the asynchronous paint completes within the specified time, the results are immediately painted.
For example, if the paint method is called and the delay is set to 20 milliseconds, the paint queue will block the Event Dispatch Thread for no longer than this time (starting from the view's invalidation). If the asynchronous paint has finished within, say 15 milliseconds, the paint method paints the result of this paint. If the paint would take, say 25 milliseconds, the paint method stops waiting after 20 milliseconds and returns the result of the previous paint.
aSynchronousDelay
- how many milliseconds to wait for asynchronous painting to complete
(starting from the beginning of the view repaint)getSynchronousDelay()
public int getSynchronousDelay()
paint(java.awt.Graphics, com.luciad.view.gxy.asynchronous.ILcdGXYAsynchronousLayerWrapper, int, com.luciad.view.gxy.ILcdGXYView)
waits for asynchronous paints. If the asynchronous paint
completes within the specified time, the results are immediately painted.setSynchronousDelay(int)
public boolean isEmpty()
ILcdGXYAsynchronousPaintQueue
isEmpty
in interface ILcdGXYAsynchronousPaintQueue
public ILcdGXYView getGXYAsynchronousView(ILcdGXYAsynchronousLayerWrapper aWrapper, int aMode, ILcdGXYView aGXYView)
ILcdGXYAsynchronousPaintQueue
getGXYAsynchronousView
in interface ILcdGXYAsynchronousPaintQueue
aWrapper
- the asynchronous layer wrapper that would be paintedaMode
- the mode indicating what should be painted, see ILcdGXYLayer.paint(java.awt.Graphics, int, com.luciad.view.gxy.ILcdGXYView)
.aGXYView
- the original view for which asynchronous paints are meant to be displayed. Paints
for unsupported views are executed synchronously.public void invokeAndWait(Runnable aRunnable) throws InterruptedException
ILcdGXYAsynchronousPaintQueue
Runnable
synchronously, but without interfering with the paint thread.
This call blocks until all
asynchronous paints and runnables have been processed, and the Runnable
returns.
The invocation is executed in the view's paint thread (typically the EDT).invokeAndWait
in interface ILcdGXYAsynchronousPaintQueue
aRunnable
- the Runnable
to execute. The run
method should take care
when waiting for another thread: if that thread in turn waits for asynchronous painting to complete,
a deadlock will occur.InterruptedException
- when the thread is interrupted while waiting for the execution
to completepublic void invokeLater(Runnable aRunnable)
ILcdGXYAsynchronousPaintQueue
Runnable
in the paint thread and returns immediately.invokeLater
in interface ILcdGXYAsynchronousPaintQueue
aRunnable
- the Runnable
to execute. The run
method should take care
when waiting for another thread: if that thread in turn waits for asynchronous painting to complete,
a deadlock will occur.public void invokeLaterInEDT(Runnable aRunnable)
ILcdGXYAsynchronousPaintQueue
Runnable
in the event dispatch thread and returns immediately.invokeLaterInEDT
in interface ILcdGXYAsynchronousPaintQueue
aRunnable
- the Runnable
to execute.public void addGXYAsynchronousPaintListener(ILcdGXYAsynchronousPaintListener aListener)
ILcdGXYAsynchronousPaintQueue
ILcdGXYAsynchronousPaintListener
to be informed of asynchronous painting events.
These events will be thrown in the asynchronous painting thread.addGXYAsynchronousPaintListener
in interface ILcdGXYAsynchronousPaintQueue
aListener
- the listener that should be notifiedpublic void removeGXYAsynchronousPaintListener(ILcdGXYAsynchronousPaintListener aListener)
ILcdGXYAsynchronousPaintQueue
ILcdGXYAsynchronousPaintListener
of asynchronous painting events.removeGXYAsynchronousPaintListener
in interface ILcdGXYAsynchronousPaintQueue
aListener
- the listener that should no longer be notified.public int getPriority()
public void setPriority(int aPriority)
aPriority
- the new priority of the internal painting threadpublic void reset() throws InterruptedException
ILcdGXYAsynchronousPaintQueue
reset
in interface ILcdGXYAsynchronousPaintQueue
InterruptedException
- when the thread is interrupted while waiting for the asynchronous paint
to complete