Changed ActiveRenderer to only permit Canvas now (instead of JFrame)
This commit is contained in:
parent
a6300d8ba5
commit
b2e29e38cd
@ -15,10 +15,11 @@
|
||||
*/
|
||||
package dorkbox.util.swing;
|
||||
|
||||
import java.awt.Canvas;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.image.BufferStrategy;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
|
||||
@ -65,19 +66,24 @@ class ActiveRenderLoop implements Runnable {
|
||||
actionHandlerLong.handle(updateDeltaNanos);
|
||||
}
|
||||
|
||||
// this needs to be synchronized because we don't want to our frame removed WHILE we are rendering it.
|
||||
// this needs to be synchronized because we don't want to our canvas removed WHILE we are rendering it.
|
||||
synchronized (SwingActiveRender.activeRenders) {
|
||||
for (int i = 0; i < SwingActiveRender.activeRenders.size(); i++) {
|
||||
Window window = SwingActiveRender.activeRenders.get(i);
|
||||
final List<Canvas> activeRenders = SwingActiveRender.activeRenders;
|
||||
|
||||
final BufferStrategy buffer = window.getBufferStrategy();
|
||||
for (Canvas canvas : activeRenders) {
|
||||
if (!canvas.isDisplayable()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BufferStrategy buffer = canvas.getBufferStrategy();
|
||||
|
||||
// maybe the frame was closed
|
||||
if (buffer != null) {
|
||||
try {
|
||||
graphics = buffer.getDrawGraphics();
|
||||
window.paint(graphics);
|
||||
canvas.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.
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (graphics != null) {
|
||||
@ -91,7 +97,6 @@ class ActiveRenderLoop implements Runnable {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sync the display on some systems (on Linux, this fixes event queue problems)
|
||||
Toolkit.getDefaultToolkit()
|
||||
|
@ -15,17 +15,14 @@
|
||||
*/
|
||||
package dorkbox.util.swing;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Canvas;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Window;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import dorkbox.util.ActionHandlerLong;
|
||||
|
||||
@ -42,7 +39,7 @@ public final
|
||||
class SwingActiveRender {
|
||||
private static Thread activeRenderThread = null;
|
||||
|
||||
static final List<Window> activeRenders = new ArrayList<Window>();
|
||||
static final List<Canvas> activeRenders = new ArrayList<Canvas>();
|
||||
static final List<ActionHandlerLong> activeRenderEvents = new CopyOnWriteArrayList<ActionHandlerLong>();
|
||||
|
||||
// volatile, so that access triggers thread synchrony, since 1.6. See the Java Language Spec, Chapter 17
|
||||
@ -56,56 +53,77 @@ class SwingActiveRender {
|
||||
|
||||
|
||||
/**
|
||||
* Enables the window to to added to an "Active Render" thread, at a target "Frames-per-second". This is to support smooth, swing-based
|
||||
* animations. <br> This works by removing this object from EDT updates, and instead manually calls paint(g) on the window, updating it
|
||||
* on our own thread.
|
||||
* Enables the canvas to to added to an "Active Render" thread, at a target "Frames-per-second". This is to support smooth, swing-based
|
||||
* animations.
|
||||
* <p>
|
||||
* This works by removing this object from EDT updates, and instead manually calls paint(g) on the canvas, updating it on our own thread.
|
||||
*
|
||||
* @param window the window to add to the ActiveRender thread.
|
||||
* @param canvas the canvas to add to the ActiveRender thread.
|
||||
*/
|
||||
@SuppressWarnings("Duplicates")
|
||||
public static
|
||||
void addActiveRender(final Window window) {
|
||||
void addActiveRender(final Canvas canvas) {
|
||||
// this should be on the EDT
|
||||
if (!EventQueue.isDispatchThread()) {
|
||||
throw new RuntimeException("adding a swing Window to be actively rendered must be done on the EDT.");
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
addActiveRender(canvas);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// setup double-buffering, so we can properly use Active-Rendering, so the animations will be smooth
|
||||
window.createBufferStrategy(2);
|
||||
|
||||
// have to specify ALL children in Window to ignore EDT paint requests
|
||||
Deque<Component> components = new ArrayDeque<Component>(8);
|
||||
components.add(window);
|
||||
|
||||
Component[] c;
|
||||
Component pop;
|
||||
while ((pop = components.poll()) != null) {
|
||||
pop.setIgnoreRepaint(true);
|
||||
|
||||
if (pop instanceof JComponent) {
|
||||
c = ((JComponent) pop).getComponents();
|
||||
Collections.addAll(components, c);
|
||||
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);
|
||||
|
||||
synchronized (activeRenders) {
|
||||
if (!hasActiveRenders) {
|
||||
setupActiveRenderThread();
|
||||
}
|
||||
|
||||
hasActiveRenders = true;
|
||||
activeRenders.add(window);
|
||||
activeRenders.add(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a window from the ActiveRender queue. This should happen when the window is closed.
|
||||
* Removes a canvas from the ActiveRender queue. This should happen when the canvas is closed.
|
||||
*
|
||||
* @param window the window to remove
|
||||
* @param canvas the canvas to remove
|
||||
*/
|
||||
public static
|
||||
void removeActiveRender(final Window window) {
|
||||
void removeActiveRender(final Canvas canvas) {
|
||||
// this should be on the EDT
|
||||
if (!EventQueue.isDispatchThread()) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
removeActiveRender(canvas);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (activeRenders) {
|
||||
activeRenders.remove(window);
|
||||
activeRenders.remove(canvas);
|
||||
|
||||
final boolean hadActiveRenders = !activeRenders.isEmpty();
|
||||
hasActiveRenders = hadActiveRenders;
|
||||
@ -115,20 +133,7 @@ class SwingActiveRender {
|
||||
}
|
||||
}
|
||||
|
||||
// have to specify ALL children in window to obey EDT paint requests
|
||||
Deque<Component> components = new ArrayDeque<Component>(8);
|
||||
components.add(window);
|
||||
|
||||
Component[] c;
|
||||
Component pop;
|
||||
while ((pop = components.poll()) != null) {
|
||||
pop.setIgnoreRepaint(false);
|
||||
|
||||
if (pop instanceof JComponent) {
|
||||
c = ((JComponent) pop).getComponents();
|
||||
Collections.addAll(components, c);
|
||||
}
|
||||
}
|
||||
canvas.setIgnoreRepaint(false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,7 +24,7 @@ class SynchronizedEventQueue extends EventQueue {
|
||||
public static final Object MUTEX = new Object();
|
||||
|
||||
private static final SynchronizedEventQueue instance = new SynchronizedEventQueue();
|
||||
private static boolean alreadyInUse = false;
|
||||
private static volatile boolean alreadyInUse = false;
|
||||
|
||||
public static synchronized
|
||||
void install() {
|
||||
|
Loading…
Reference in New Issue
Block a user