From f9915fafcbfd12874ef85b07dbae8169c223d79e Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 25 Jun 2018 22:38:36 +0200 Subject: [PATCH] Changed Swing Active Renderer to use awt.component instead of awt.Canvas --- src/dorkbox/util/swing/ActiveRenderLoop.java | 26 +++----- src/dorkbox/util/swing/SwingActiveRender.java | 62 +++++++------------ 2 files changed, 32 insertions(+), 56 deletions(-) diff --git a/src/dorkbox/util/swing/ActiveRenderLoop.java b/src/dorkbox/util/swing/ActiveRenderLoop.java index 1efbc94..672a853 100644 --- a/src/dorkbox/util/swing/ActiveRenderLoop.java +++ b/src/dorkbox/util/swing/ActiveRenderLoop.java @@ -15,10 +15,9 @@ */ package dorkbox.util.swing; -import java.awt.Canvas; +import java.awt.Component; import java.awt.Graphics; import java.awt.Toolkit; -import java.awt.image.BufferStrategy; import java.util.List; import javax.swing.JComponent; @@ -68,31 +67,24 @@ class ActiveRenderLoop implements Runnable { // this needs to be synchronized because we don't want to our canvas removed WHILE we are rendering it. synchronized (SwingActiveRender.activeRenders) { - final List activeRenders = SwingActiveRender.activeRenders; + final List activeRenders = SwingActiveRender.activeRenders; - for (Canvas canvas : activeRenders) { - if (!canvas.isDisplayable()) { + for (Component component : activeRenders) { + if (!component.isDisplayable()) { continue; } - BufferStrategy buffer = canvas.getBufferStrategy(); - - // maybe the frame was closed + // maybe the frame was closed, so we must be in a try/catch issue #11 try { - graphics = buffer.getDrawGraphics(); - canvas.paint(graphics); + graphics = component.getGraphics(); + component.paint(graphics); } catch (Exception e) { - // the frame can be close as well. can get a "java.lang.IllegalStateException: Component must have a valid - // peer" if it's already be closed during the getDrawGraphics call. + // the canvas can be closed as well. can get a "java.lang.IllegalStateException: Component must have a valid peer" if + // it's already be closed during the getDrawGraphics call. e.printStackTrace(); } finally { if (graphics != null) { graphics.dispose(); - - // blit the back buffer to the screen - if (buffer != null && !buffer.contentsLost()) { - buffer.show(); - } } } } diff --git a/src/dorkbox/util/swing/SwingActiveRender.java b/src/dorkbox/util/swing/SwingActiveRender.java index eb99118..5d0bf8f 100644 --- a/src/dorkbox/util/swing/SwingActiveRender.java +++ b/src/dorkbox/util/swing/SwingActiveRender.java @@ -15,31 +15,30 @@ */ package dorkbox.util.swing; -import java.awt.Canvas; +import java.awt.Component; import java.awt.EventQueue; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; -import javax.swing.JComponent; import javax.swing.SwingUtilities; import dorkbox.util.ActionHandlerLong; /** - * Contains all of the appropriate logic to setup and render via "Active" rendering (instead of "Passive" rendering). This permits us to - * render Windows (and their contents), OFF of the EDT - even though there are other frames/components that are ON the EDT.
Because we - * still want to react to mouse events, etc on the EDT, we do not completely remove the EDT -- we merely allow us to "synchronize" the EDT - * object to our thread. It's a little bit hacky, but it works beautifully, and permits MUCH nicer animations.
- *

- * It is also important to REMEMBER -- if you add a component to an actively managed Window, YOU MUST make sure to call {@link - * JComponent#setIgnoreRepaint(boolean)} otherwise this component will "fight" on the EDT for updates. + * Contains all of the appropriate logic to setup and render via "Active" rendering (instead of "Passive" rendering). + * + * This permits us to render components OFF of the EDT - even though there are other frames/components that are ON the EDT. + *
+ * Because we still want to react to mouse events, etc on the EDT, we do not completely remove the EDT -- we merely allow us + * to "synchronize" the EDT object to our thread. It's a little bit hacky, but it works beautifully, and permits MUCH nicer animations. + *
*/ public final class SwingActiveRender { private static Thread activeRenderThread = null; - static final List activeRenders = new ArrayList(); + static final List activeRenders = new ArrayList(); static final List activeRenderEvents = new CopyOnWriteArrayList(); // volatile, so that access triggers thread synchrony, since 1.6. See the Java Language Spec, Chapter 17 @@ -53,45 +52,30 @@ class SwingActiveRender { /** - * Enables the canvas to to added to an "Active Render" thread, at a target "Frames-per-second". This is to support smooth, swing-based + * Enables the component to to added to an "Active Render" thread, at a target "Frames-per-second". This is to support smooth, swing-based * animations. *

- * This works by removing this object from EDT updates, and instead manually calls paint(g) on the canvas, updating it on our own thread. + * This works by removing this object from EDT updates and manually calls paint on the component, updating it on our own thread, but + * still remaining synchronized with the EDT. * - * @param canvas the canvas to add to the ActiveRender thread. + * @param component the component to add to the ActiveRender thread. */ @SuppressWarnings("Duplicates") public static - void addActiveRender(final Canvas canvas) { + void addActiveRender(final Component component) { // this should be on the EDT if (!EventQueue.isDispatchThread()) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - addActiveRender(canvas); + addActiveRender(component); } }); return; } - // setup double-buffering, so we can properly use Active-Rendering, so the animations will be smooth - try { - canvas.createBufferStrategy(2); - } catch (Exception e) { - // sometimes it's added too early. Postpone the event until later - // note: this is different than SwingUtil, because we MUST invoke it later (and not in the current thread) - SwingUtilities.invokeLater(new Runnable() { - @Override - public - void run() { - addActiveRender(canvas); - } - }); - return; - } - - canvas.setIgnoreRepaint(true); + component.setIgnoreRepaint(true); synchronized (activeRenders) { if (!hasActiveRenders) { @@ -99,31 +83,31 @@ class SwingActiveRender { } hasActiveRenders = true; - activeRenders.add(canvas); + activeRenders.add(component); } } /** - * Removes a canvas from the ActiveRender queue. This should happen when the canvas is closed. + * Removes a component from the ActiveRender queue. This should happen when the component is closed. * - * @param canvas the canvas to remove + * @param component the component to remove */ public static - void removeActiveRender(final Canvas canvas) { + void removeActiveRender(final Component component) { // this should be on the EDT if (!EventQueue.isDispatchThread()) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - removeActiveRender(canvas); + removeActiveRender(component); } }); return; } synchronized (activeRenders) { - activeRenders.remove(canvas); + activeRenders.remove(component); final boolean hadActiveRenders = !activeRenders.isEmpty(); hasActiveRenders = hadActiveRenders; @@ -133,7 +117,7 @@ class SwingActiveRender { } } - canvas.setIgnoreRepaint(false); + component.setIgnoreRepaint(false); } /**