Class TLcdGXYAsynchronousPaintQueue

java.lang.Object
com.luciad.view.gxy.asynchronous.TLcdGXYAsynchronousPaintQueue
All Implemented Interfaces:
ILcdGXYAsynchronousPaintQueue

public class TLcdGXYAsynchronousPaintQueue extends Object implements ILcdGXYAsynchronousPaintQueue
This 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
The following layer ordering will yield an incorrect visual result, because the layers of Q1 are not adjacent:
  • 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:
  • Field Details

    • EVERYTHING

      public static final int EVERYTHING
      Asynchronous painting mode constant that specifies to paint everything asynchronously: bodies, labels, selection,...
      See Also:
    • BODIES

      public static final int BODIES
      Asynchronous 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_SKIP
      Asynchronous 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

      public TLcdGXYAsynchronousPaintQueue(ILcdGXYView aView)
      This convenience constructor is equivalent with calling TLcdGXYAsynchronousPaintQueue( ILcdGXYView aView, EVERYTHING, 0, 200, 25 )
      See Also:
    • TLcdGXYAsynchronousPaintQueue

      public TLcdGXYAsynchronousPaintQueue(ILcdGXYView aView, int aPaintMode)
      This convenience constructor is equivalent with calling TLcdGXYAsynchronousPaintQueue( 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 on 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.
      Parameters:
      aView - the view for which to paint asynchronously
      aPaintMode - indicates what part of the layers should be painted asynchronously
      aBorderFactor - 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.
  • 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 is true 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 either 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.
      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.
      Returns true if tracing is enabled for this class.
      Returns:
      true if tracing is enabled for this class, false otherwise.
    • getGXYView

      public ILcdGXYView 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 or BODIES_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

      public void setInterruptMode(TLcdGXYAsynchronousPaintQueue.InterruptMode aInterruptMode)
      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 interface ILcdGXYAsynchronousPaintQueue
      Parameters:
      aGraphics - the graphics to use for painting
      aWrapper - the asynchronous layer wrapper that should be painted
      aMode - 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.
    • 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 long 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.

      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 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.
      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 interface ILcdGXYAsynchronousPaintQueue
      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 interface ILcdGXYAsynchronousPaintQueue
      Parameters:
      aWrapper - the asynchronous layer wrapper that would be painted
      aMode - 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.
      Returns:
      the view that is used for asynchronous painting
    • invokeAndWait

      public void invokeAndWait(Runnable aRunnable) throws InterruptedException
      Description copied from interface: ILcdGXYAsynchronousPaintQueue
      Executes the given 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).
      Specified by:
      invokeAndWait in interface ILcdGXYAsynchronousPaintQueue
      Parameters:
      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.
      Throws:
      InterruptedException - when the thread is interrupted while waiting for the execution to complete
    • invokeLater

      public void invokeLater(Runnable aRunnable)
      Description copied from interface: ILcdGXYAsynchronousPaintQueue
      Executes the given Runnable in the paint thread and returns immediately.
      Specified by:
      invokeLater in interface ILcdGXYAsynchronousPaintQueue
      Parameters:
      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.
    • invokeLaterInEDT

      public void invokeLaterInEDT(Runnable aRunnable)
      Description copied from interface: ILcdGXYAsynchronousPaintQueue
      Executes the given Runnable in the event dispatch thread and returns immediately.
      Specified by:
      invokeLaterInEDT in interface ILcdGXYAsynchronousPaintQueue
      Parameters:
      aRunnable - the Runnable to execute.
    • addGXYAsynchronousPaintListener

      public void addGXYAsynchronousPaintListener(ILcdGXYAsynchronousPaintListener aListener)
      Description copied from interface: ILcdGXYAsynchronousPaintQueue
      Registers an ILcdGXYAsynchronousPaintListener to be informed of asynchronous painting events. These events will be thrown in the asynchronous painting thread.
      Specified by:
      addGXYAsynchronousPaintListener in interface ILcdGXYAsynchronousPaintQueue
      Parameters:
      aListener - the listener that should be notified
    • removeGXYAsynchronousPaintListener

      public void removeGXYAsynchronousPaintListener(ILcdGXYAsynchronousPaintListener aListener)
      Description copied from interface: ILcdGXYAsynchronousPaintQueue
      Stops informing the given ILcdGXYAsynchronousPaintListener of asynchronous painting events.
      Specified by:
      removeGXYAsynchronousPaintListener in interface ILcdGXYAsynchronousPaintQueue
      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

      public void reset() throws InterruptedException
      Description copied from interface: ILcdGXYAsynchronousPaintQueue
      Clears all cached images and paint requests. Waits for asynchronous painting to finish.
      Specified by:
      reset in interface ILcdGXYAsynchronousPaintQueue
      Throws:
      InterruptedException - when the thread is interrupted while waiting for the asynchronous paint to complete
    • toString

      public String toString()
      Overrides:
      toString in class Object