-
Bug
-
Resolution: Fixed
-
P4
-
8
-
64-bit Windows 7
Java 1.8.0-ea-b119
Java HotSpot 64-bit Server VM (build 25.0-b61, mixed mode)
javafx.properties file reports javafx.runtime.version=8.0.0
I've written an AnimPlasma application that animates a colorful plasma image on JavaFX's canvas. The source code appears below (and an explanation of the problem follows):
import javafx.animation.PauseTransition;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.VPos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.Reflection;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;
public class AnimPlasma extends Application
{
private int[] palette;
private byte[][] plasma;
private int[] colors;
private GraphicsContext gc;
@Override
public void start(final Stage primaryStage)
{
primaryStage.setTitle("Animated Plasma");
primaryStage.setWidth(600);
primaryStage.setHeight(600);
final Group group = new Group();
Text text = new Text();
text.setText("Animated Plasma");
text.setFill(Color.YELLOW);
text.setFont(new Font("Arial BOLD", 24.0));
text.setEffect(new DropShadow());
text.xProperty().bind(primaryStage.widthProperty()
.subtract(text.layoutBoundsProperty().getValue().getWidth())
.divide(2));
text.setY(30.0);
text.setTextOrigin(VPos.TOP);
group.getChildren().add(text);
Canvas canvas = new Canvas(400, 400);
canvas.setTranslateX(100);
canvas.setTranslateY(100);
gc = canvas.getGraphicsContext2D();
group.getChildren().add(canvas);
/*
DropShadow ds = new DropShadow();
ds.setInput(new Reflection());
group.setEffect(ds);
*/
Reflection r = new Reflection();
r.setInput(new DropShadow()); // This line leads to NullPointerException.
group.setEffect(r);
LinearGradient lg = new LinearGradient(0.0, 0.0, 0.0, 1.0, true,
CycleMethod.NO_CYCLE,
new Stop(0, Color.BLUE),
new Stop(1.0, Color.BLUEVIOLET));
Scene scene = new Scene(group, lg);
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.show();
setup(canvas);
final PauseTransition pt = new PauseTransition(Duration.millis(30));
pt.setCycleCount(1);
pt.setOnFinished(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent ae)
{
update(canvas);
pt.play();
}
});
pt.play();
}
void setup(Canvas canvas)
{
palette = new int[256];
for (int i = 0; i < palette.length; i++)
{
Color color = Color.hsb(i/255.0*360, 1.0, 1.0);
int red = (int) (color.getRed()*255);
int grn = (int) (color.getGreen()*255);
int blu = (int) (color.getBlue()*255);
palette[i] = (red << 16)|(grn << 8)|blu;
}
plasma = new byte[(int) canvas.getHeight()][];
for (int i = 0; i < plasma.length; i++)
plasma[i] = new byte[(int) canvas.getWidth()];
colors = new int[(int) (canvas.getWidth()*canvas.getHeight())];
}
void update(Canvas canvas)
{
int width = (int) canvas.getWidth();
int height = (int) canvas.getHeight();
for (int row = 0; row < height; row++)
for (int col = 0; col < width; col++)
plasma[row][col] =
(byte) ((128.0+128.0*Math.cos(row/8.0)+
128.0+128.0*Math.cos(col/8.0))/2);
int shift = (int) System.currentTimeMillis()/5;
int base = 0;
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
colors[base+col] = palette[(plasma[row][col]+shift)&255];
int r = (colors[base+col]>>16)&255;
int g = (colors[base+col]>>8)&255;
int b = colors[base+col]&255;
gc.setFill(Color.rgb(r, g, b));
gc.fillRect(row, col, 1, 1);
}
base += width;
}
}
public static void main(String[] args)
{
launch(args);
}
}
In the following code sequence, r.setInput(new DropShadow()); leads to repeated runtime error messages:
Reflection r = new Reflection();
r.setInput(new DropShadow()); // This line leads to NullPointerException.
group.setEffect(r);
The error message appears below:
java.lang.NullPointerException
at com.sun.scenario.effect.FilterEffect.getBounds(FilterEffect.java:67)
at com.sun.scenario.effect.BoxShadow.getBounds(BoxShadow.java:367)
at com.sun.scenario.effect.Offset.getBounds(Offset.java:145)
at com.sun.scenario.effect.FilterEffect.getBounds(FilterEffect.java:72)
at com.sun.scenario.effect.DelegateEffect.getBounds(DelegateEffect.java:60)
at com.sun.scenario.effect.Effect.getBounds(Effect.java:325)
at com.sun.scenario.effect.Reflection.getDirtyRegions(Reflection.java:271)
at com.sun.javafx.sg.prism.NGNode.applyEffect(NGNode.java:2471)
at com.sun.javafx.sg.prism.NGNode.accumulateGroupDirtyRegion(NGNode.java:1209)
at com.sun.javafx.sg.prism.NGNode.accumulateDirtyRegions(NGNode.java:1033)
at com.sun.javafx.tk.quantum.ViewPainter.paintImpl(ViewPainter.java:236)
at com.sun.javafx.tk.quantum.PresentingPainter.run(PresentingPainter.java:89)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:129)
at java.lang.Thread.run(Thread.java:744)
When I comment out r.setInput(new DropShadow());, everything works fine except that there is no drop shadow. Interestingly, if I replace the three-line code sequence with the following code sequence:
DropShadow ds = new DropShadow();
ds.setInput(new Reflection());
group.setEffect(ds);
there is no problem.
Jeff
import javafx.animation.PauseTransition;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.VPos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.Reflection;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;
public class AnimPlasma extends Application
{
private int[] palette;
private byte[][] plasma;
private int[] colors;
private GraphicsContext gc;
@Override
public void start(final Stage primaryStage)
{
primaryStage.setTitle("Animated Plasma");
primaryStage.setWidth(600);
primaryStage.setHeight(600);
final Group group = new Group();
Text text = new Text();
text.setText("Animated Plasma");
text.setFill(Color.YELLOW);
text.setFont(new Font("Arial BOLD", 24.0));
text.setEffect(new DropShadow());
text.xProperty().bind(primaryStage.widthProperty()
.subtract(text.layoutBoundsProperty().getValue().getWidth())
.divide(2));
text.setY(30.0);
text.setTextOrigin(VPos.TOP);
group.getChildren().add(text);
Canvas canvas = new Canvas(400, 400);
canvas.setTranslateX(100);
canvas.setTranslateY(100);
gc = canvas.getGraphicsContext2D();
group.getChildren().add(canvas);
/*
DropShadow ds = new DropShadow();
ds.setInput(new Reflection());
group.setEffect(ds);
*/
Reflection r = new Reflection();
r.setInput(new DropShadow()); // This line leads to NullPointerException.
group.setEffect(r);
LinearGradient lg = new LinearGradient(0.0, 0.0, 0.0, 1.0, true,
CycleMethod.NO_CYCLE,
new Stop(0, Color.BLUE),
new Stop(1.0, Color.BLUEVIOLET));
Scene scene = new Scene(group, lg);
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.show();
setup(canvas);
final PauseTransition pt = new PauseTransition(Duration.millis(30));
pt.setCycleCount(1);
pt.setOnFinished(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent ae)
{
update(canvas);
pt.play();
}
});
pt.play();
}
void setup(Canvas canvas)
{
palette = new int[256];
for (int i = 0; i < palette.length; i++)
{
Color color = Color.hsb(i/255.0*360, 1.0, 1.0);
int red = (int) (color.getRed()*255);
int grn = (int) (color.getGreen()*255);
int blu = (int) (color.getBlue()*255);
palette[i] = (red << 16)|(grn << 8)|blu;
}
plasma = new byte[(int) canvas.getHeight()][];
for (int i = 0; i < plasma.length; i++)
plasma[i] = new byte[(int) canvas.getWidth()];
colors = new int[(int) (canvas.getWidth()*canvas.getHeight())];
}
void update(Canvas canvas)
{
int width = (int) canvas.getWidth();
int height = (int) canvas.getHeight();
for (int row = 0; row < height; row++)
for (int col = 0; col < width; col++)
plasma[row][col] =
(byte) ((128.0+128.0*Math.cos(row/8.0)+
128.0+128.0*Math.cos(col/8.0))/2);
int shift = (int) System.currentTimeMillis()/5;
int base = 0;
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
colors[base+col] = palette[(plasma[row][col]+shift)&255];
int r = (colors[base+col]>>16)&255;
int g = (colors[base+col]>>8)&255;
int b = colors[base+col]&255;
gc.setFill(Color.rgb(r, g, b));
gc.fillRect(row, col, 1, 1);
}
base += width;
}
}
public static void main(String[] args)
{
launch(args);
}
}
In the following code sequence, r.setInput(new DropShadow()); leads to repeated runtime error messages:
Reflection r = new Reflection();
r.setInput(new DropShadow()); // This line leads to NullPointerException.
group.setEffect(r);
The error message appears below:
java.lang.NullPointerException
at com.sun.scenario.effect.FilterEffect.getBounds(FilterEffect.java:67)
at com.sun.scenario.effect.BoxShadow.getBounds(BoxShadow.java:367)
at com.sun.scenario.effect.Offset.getBounds(Offset.java:145)
at com.sun.scenario.effect.FilterEffect.getBounds(FilterEffect.java:72)
at com.sun.scenario.effect.DelegateEffect.getBounds(DelegateEffect.java:60)
at com.sun.scenario.effect.Effect.getBounds(Effect.java:325)
at com.sun.scenario.effect.Reflection.getDirtyRegions(Reflection.java:271)
at com.sun.javafx.sg.prism.NGNode.applyEffect(NGNode.java:2471)
at com.sun.javafx.sg.prism.NGNode.accumulateGroupDirtyRegion(NGNode.java:1209)
at com.sun.javafx.sg.prism.NGNode.accumulateDirtyRegions(NGNode.java:1033)
at com.sun.javafx.tk.quantum.ViewPainter.paintImpl(ViewPainter.java:236)
at com.sun.javafx.tk.quantum.PresentingPainter.run(PresentingPainter.java:89)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:129)
at java.lang.Thread.run(Thread.java:744)
When I comment out r.setInput(new DropShadow());, everything works fine except that there is no drop shadow. Interestingly, if I replace the three-line code sequence with the following code sequence:
DropShadow ds = new DropShadow();
ds.setInput(new Reflection());
group.setEffect(ds);
there is no problem.
Jeff