Class TLcdGXYAsynchronousPaintQueue
- All Implemented Interfaces:
ILcdGXYAsynchronousPaintQueue
ILcdGXYAsynchronousPaintQueue
paints layers asynchronously in a background
thread, using off-screen image buffers.
How it works
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.
How to assign paint queues
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:
- synchronous layer
- asynchronous layer from paint queue Q1
- asynchronous layer from paint queue Q1
- asynchronous layer from paint queue Q2
- asynchronous layer from paint queue Q1
- synchronous layer
- asynchronous layer from paint queue Q2
- asynchronous layer from paint queue Q1
Accelerating compositing operations
For high-resolution displays, it may be interesting to speed up compositing operations by using volatile images. This can be enabled by setting the "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.
- Since:
- 7.2
- See Also:
-
Nested Class Summary
Modifier and TypeClassDescriptionstatic enum
Enumeration of the interrupt modes. -
Field Summary
Modifier and TypeFieldDescriptionstatic final int
Asynchronous painting mode constant that specifies to paint only bodies asynchronously.static final int
Asynchronous painting mode constant that specifies to paint only bodies asynchronously.static final int
Asynchronous painting mode constant that specifies to paint everything asynchronously: bodies, labels, selection,... -
Constructor Summary
ConstructorDescriptionThis convenience constructor is equivalent with callingTLcdGXYAsynchronousPaintQueue( ILcdGXYView aView, EVERYTHING, 0, 200, 25 )
TLcdGXYAsynchronousPaintQueue
(ILcdGXYView aView, int aPaintMode) This convenience constructor is equivalent with callingTLcdGXYAsynchronousPaintQueue( 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. -
Method Summary
Modifier and TypeMethodDescriptionvoid
Registers anILcdGXYAsynchronousPaintListener
to be informed of asynchronous painting events.double
Returns the relative size of the surplus border that is painted.getGXYAsynchronousView
(ILcdGXYAsynchronousLayerWrapper aWrapper, int aMode, ILcdGXYView aGXYView) Returns the view on which the asynchronous paint requests are actually executed.Returns the view for which this painter paints asynchronously.int
Returns the interval for which to display intermediary updates.Returns the interrupt mode.int
Returns what modes are painted asynchronously.int
Returns the current thread priority of the internal painting thread.int
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
Returns how longpaint(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 givenRunnable
synchronously, but without interfering with the paint thread.void
invokeLater
(Runnable aRunnable) Executes the givenRunnable
in the paint thread and returns immediately.void
invokeLaterInEDT
(Runnable aRunnable) Executes the givenRunnable
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
Returns true if ongoing paints are stopped when new paints are scheduled.boolean
Deprecated.This method has been deprecated.void
paint
(Graphics aGraphics, ILcdGXYAsynchronousLayerWrapper aWrapper, int aMode, ILcdGXYView aGXYView) Paints an image of the painted layers using the given graphics.void
Stops informing the givenILcdGXYAsynchronousPaintListener
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.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 longpaint(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.toString()
-
Field Details
-
EVERYTHING
public static final int EVERYTHINGAsynchronous painting mode constant that specifies to paint everything asynchronously: bodies, labels, selection,...- See Also:
-
BODIES
public static final int BODIESAsynchronous painting mode constant that specifies to paint only bodies asynchronously. Labels and selection are still painted synchronously.- See Also:
-
BODIES_AND_SKIP
public static final int BODIES_AND_SKIPAsynchronous painting mode constant that specifies to paint only bodies asynchronously. Labels and selection are not painted, unless the painting of the bodies has been completed, in which case they are painted synchronously.- See Also:
-
-
Constructor Details
-
TLcdGXYAsynchronousPaintQueue
This convenience constructor is equivalent with callingTLcdGXYAsynchronousPaintQueue( ILcdGXYView aView, EVERYTHING, 0, 200, 25 )
- See Also:
-
TLcdGXYAsynchronousPaintQueue
This convenience constructor is equivalent with callingTLcdGXYAsynchronousPaintQueue( ILcdGXYView aView, int aPaintMode, 0, 200, 25 )
- See Also:
-
TLcdGXYAsynchronousPaintQueue
public TLcdGXYAsynchronousPaintQueue(ILcdGXYView aView, int aPaintMode, double aBorderFactor, int aSkipDelay, int aSynchronousDelay) Creates a new asynchronous paint queue for the given view. The current implementations supports asynchronous painting onTLcdGXYViewJPanel
,TLcdGXYViewJPanelLightWeight
, andTLcdGXYViewBufferedImage
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.
- Parameters:
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 byaBorderFactor
, 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 longpaint(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.
-
-
Method Details
-
setClassTraceOn
public static void setClassTraceOn(boolean aClassTraceOn) Deprecated.This method has been deprecated. It is recommended to use the standard Java logging framework directly.Enables tracing for all instances of this class. If the argument istrue
then all log messages are recorded, otherwise only the informative, warning and error messages are recorded.- Parameters:
aClassTraceOn
- if true then all log messages are recorded, otherwise only the informative, warning and error messages are recorded.
-
setTraceOn
public void setTraceOn(boolean aTraceOn) Deprecated.This method has been deprecated. It is recommended to use the standard Java logging framework directly.Enables tracing for this class instance. Calling this method with eithertrue
orfalse
as argument automatically turns off tracing for all other class instances for whichsetTraceOn
has not been called. If the argument isfalse
then only the informative, warning and error log messages are recorded.- Parameters:
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.
-
isTraceOn
public boolean isTraceOn()Deprecated.This method has been deprecated. It is recommended to use the standard Java logging framework directly.Returnstrue
if tracing is enabled for this class.- Returns:
- true if tracing is enabled for this class, false otherwise.
-
getGXYView
Returns the view for which this painter paints asynchronously.- Returns:
- the view for which this painter paints asynchronously
-
getPaintMode
public int getPaintMode()Returns what modes are painted asynchronously.- Returns:
- one of
EVERYTHING
,BODIES
orBODIES_AND_SKIP
-
getBorderFactor
public double getBorderFactor()Returns the relative size of the surplus border that is painted.- Returns:
- the relative amount by which the image is enlarged on each side
-
setBorderFactor
public void setBorderFactor(double aFactor) Sets the relative size of the surplus border that is painted. A high value increases the memory usage and waiting time of the asynchronous painting, but will often give immediate imagery for small pan and zoom operations.- Parameters:
aFactor
- the relative amount by which to enlarge the image on each side.
-
setIntermediateUpdateInterval
public void setIntermediateUpdateInterval(int aInterval) Sets the interval for which to display intermediary updates. When non-zero, the currently active asynchronous paint is displayed instead of the last completed paint, and refreshed according to the specified interval.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.
- Parameters:
aInterval
- an interval in milliseconds specifying a refresh rate for displaying intermediate results on the view- See Also:
-
getIntermediateUpdateInterval
public int getIntermediateUpdateInterval()Returns the interval for which to display intermediary updates. When non-zero, the currently active asynchronous paint is displayed instead of the last completed paint, and refreshed according to the specified interval.- Returns:
- an interval in milliseconds, specifying a refresh rate for displaying intermediate results on the view
- See Also:
-
isInterruptPainting
public boolean isInterruptPainting()Returns true if ongoing paints are stopped when new paints are scheduled. By default, this behavior is active.- Returns:
- true if ongoing paints are stopped when new paints are scheduled
- See Also:
-
setInterruptPainting
public void setInterruptPainting(boolean aInterruptPainting) Determines whether to stop ongoing asynchronous paints when new paints are scheduled.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.
- Parameters:
aInterruptPainting
- true if asynchronous paints must be interrupted- See Also:
-
getInterruptMode
Returns the interrupt mode. By default the interrupt mode is InterruptMode.NON_OVERLAPPING_PAINTS_ONLY.- Returns:
- the interrupt mode.
- See Also:
-
setInterruptMode
Sets the interrupt mode. For this setting to have any effect,isInterruptPainting()
should return true.By default the interrupt mode is InterruptMode.NON_OVERLAPPING_PAINTS_ONLY.
- Parameters:
aInterruptMode
- the interrupt mode.- See Also:
-
paint
public void paint(Graphics aGraphics, ILcdGXYAsynchronousLayerWrapper aWrapper, int aMode, ILcdGXYView aGXYView) Description copied from interface:ILcdGXYAsynchronousPaintQueue
Paints an image of the painted layers using the given graphics. If a valid image is not available for the mode, this operation queues an asynchronous paint request, in order to create one. The parent view will then be asked to repaint itself when the asynchronous painting is completed.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).
- Specified by:
paint
in interfaceILcdGXYAsynchronousPaintQueue
- Parameters:
aGraphics
- the graphics to use for paintingaWrapper
- the asynchronous layer wrapper that should be paintedaMode
- the mode indicating what should be painted, seeILcdGXYLayer.paint(java.awt.Graphics, int, com.luciad.view.gxy.ILcdGXYView)
.aGXYView
- the view for which the layer should be painted.
-
setSkipDelay
public 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. Setting this to a higher value avoids rapid flickering.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.
- Parameters:
aDelay
- how many milliseconds to wait before displaying synchronous content, after skipping them.- See Also:
-
getSkipDelay
public 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.- Returns:
- how many milliseconds to wait before displaying synchronous content, after skipping them.
- See Also:
-
setSynchronousDelay
public void setSynchronousDelay(int aSynchronousDelay) Sets how longpaint(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.
- Parameters:
aSynchronousDelay
- how many milliseconds to wait for asynchronous painting to complete (starting from the beginning of the view repaint)- See Also:
-
getSynchronousDelay
public int getSynchronousDelay()Returns how longpaint(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.- Returns:
- how many milliseconds to wait for asynchronous painting to complete (starting from the beginning of the view repaint)
- See Also:
-
isEmpty
public boolean isEmpty()Description copied from interface:ILcdGXYAsynchronousPaintQueue
Returns true if the paint queue is not painting and it has no paint requests to finish. When called on the event dispatch thread, it should guarantee that no painting occurs while the caller holds the thread.- Specified by:
isEmpty
in interfaceILcdGXYAsynchronousPaintQueue
- Returns:
- true when no painting will occur while the caller holds the thread
-
getGXYAsynchronousView
public ILcdGXYView getGXYAsynchronousView(ILcdGXYAsynchronousLayerWrapper aWrapper, int aMode, ILcdGXYView aGXYView) Description copied from interface:ILcdGXYAsynchronousPaintQueue
Returns the view on which the asynchronous paint requests are actually executed. In the painting thread, the asynchronous view replaces the given view when painting the given asynchronous layer with the given painting mode. Its images are then used as image buffers that can be composited in the actual view.- Specified by:
getGXYAsynchronousView
in interfaceILcdGXYAsynchronousPaintQueue
- Parameters:
aWrapper
- the asynchronous layer wrapper that would be paintedaMode
- the mode indicating what should be painted, seeILcdGXYLayer.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.- Returns:
- the view that is used for asynchronous painting
-
invokeAndWait
Description copied from interface:ILcdGXYAsynchronousPaintQueue
Executes the givenRunnable
synchronously, but without interfering with the paint thread. This call blocks until all asynchronous paints and runnables have been processed, and theRunnable
returns. The invocation is executed in the view's paint thread (typically the EDT).- Specified by:
invokeAndWait
in interfaceILcdGXYAsynchronousPaintQueue
- Parameters:
aRunnable
- theRunnable
to execute. Therun
method should take care when waiting for another thread: if that thread in turn waits for asynchronous painting to complete, a deadlock will occur.- Throws:
InterruptedException
- when the thread is interrupted while waiting for the execution to complete
-
invokeLater
Description copied from interface:ILcdGXYAsynchronousPaintQueue
Executes the givenRunnable
in the paint thread and returns immediately.- Specified by:
invokeLater
in interfaceILcdGXYAsynchronousPaintQueue
- Parameters:
aRunnable
- theRunnable
to execute. Therun
method should take care when waiting for another thread: if that thread in turn waits for asynchronous painting to complete, a deadlock will occur.
-
invokeLaterInEDT
Description copied from interface:ILcdGXYAsynchronousPaintQueue
Executes the givenRunnable
in the event dispatch thread and returns immediately.- Specified by:
invokeLaterInEDT
in interfaceILcdGXYAsynchronousPaintQueue
- Parameters:
aRunnable
- theRunnable
to execute.
-
addGXYAsynchronousPaintListener
Description copied from interface:ILcdGXYAsynchronousPaintQueue
Registers anILcdGXYAsynchronousPaintListener
to be informed of asynchronous painting events. These events will be thrown in the asynchronous painting thread.- Specified by:
addGXYAsynchronousPaintListener
in interfaceILcdGXYAsynchronousPaintQueue
- Parameters:
aListener
- the listener that should be notified
-
removeGXYAsynchronousPaintListener
Description copied from interface:ILcdGXYAsynchronousPaintQueue
Stops informing the givenILcdGXYAsynchronousPaintListener
of asynchronous painting events.- Specified by:
removeGXYAsynchronousPaintListener
in interfaceILcdGXYAsynchronousPaintQueue
- Parameters:
aListener
- the listener that should no longer be notified.
-
getPriority
public int getPriority()Returns the current thread priority of the internal painting thread.- Returns:
- the internal painting thread's priority
-
setPriority
public void setPriority(int aPriority) Sets the thread priority to be used by the internal painting thread.- Parameters:
aPriority
- the new priority of the internal painting thread
-
reset
Description copied from interface:ILcdGXYAsynchronousPaintQueue
Clears all cached images and paint requests. Waits for asynchronous painting to finish.- Specified by:
reset
in interfaceILcdGXYAsynchronousPaintQueue
- Throws:
InterruptedException
- when the thread is interrupted while waiting for the asynchronous paint to complete
-
toString
-