As it is, the ball in the foreground image fades, but
the background fades to black along with it.
Is there any way I can 'have my cake and eat it too'?
<sscce>
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
public class FadeComponent
extends JPanel
implements Runnable {
BufferedImage bg;
BufferedImage fg;
BufferedImage buffer;
int w = 300;
int h = w;
int x=0;
int y=0;
int size = 10;
FadeComponent() {
bg = new BufferedImage(
w, h, BufferedImage.TYPE_INT_ARGB );
Graphics gBG = bg.getGraphics();
gBG.setColor(Color.WHITE);
gBG.fillRect(0,0,w,h);
gBG.setColor(Color.BLACK);
gBG.drawLine(0,0,w,h);
gBG.drawLine(0,h,w,0);
fg = new BufferedImage(
w, h, BufferedImage.TYPE_INT_ARGB );
Graphics gFG = bg.getGraphics();
gFG.setColor(Color.RED);
gFG.fillOval(x,y,size,size);
buffer = new BufferedImage(
w, h, BufferedImage.TYPE_INT_ARGB );
Thread t = new Thread(this);
t.start();
}
public void run() {
while(true) {
repaint();
try {
Thread.sleep(40);
} catch(InterruptedException ie) {
// continue..
}
}
}
public Dimension getPreferredSize() {
return new Dimension(300,300);
}
public void paintComponent(Graphics g) {
Graphics gBuffer = buffer.getGraphics();
gBuffer.drawImage( bg,0,0,w,h,null );
Graphics gFG = fg.getGraphics();
gFG.setColor( new Color(0,0,0,10) );
gFG.fillRect( 0,0,w,h );
gFG.setColor(Color.RED);
gFG.fillOval(++x,++y,size,size);
gBuffer.drawImage( fg,0,0,w,h,null );
g.drawImage( buffer,0,0,w,h,null );
if (x>w) {
x=0;
y=0;
}
}
public static void main(String[] args) {
JFrame f = new JFrame( "Fade Test" );
FadeComponent fc = new FadeComponent();
f.getContentPane().add(fc);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
</sscce>
Andrew T.
don't draw bg image to buffer, draw it to fg and throw away black rect.
I optimized also a bit your code (caching of Graphics):
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
public class FadeComponent extends JPanel implements Runnable {
BufferedImage bg;
BufferedImage fg;
Graphics2D gFG;
BufferedImage buffer;
Graphics gBuffer;
AlphaComposite composite =
AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .1f);
int w = 300;
int h = w;
int x = 0;
int y = 0;
int size = 10;
FadeComponent() {
bg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics gBG = bg.getGraphics();
gBG.setColor(Color.WHITE);
gBG.fillRect(0, 0, w, h);
gBG.setColor(Color.BLACK);
gBG.drawLine(0, 0, w, h);
gBG.drawLine(0, h, w, 0);
fg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
gFG = fg.createGraphics();
gFG.setColor(Color.RED);
gFG.fillOval(x, y, size, size);
buffer = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
gBuffer = buffer.createGraphics();
Thread t = new Thread(this);
t.start();
}
public void run() {
while (true) {
repaint();
try {
Thread.sleep(40);
}
catch (InterruptedException ie) {
// continue..
}
}
}
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
public void paintComponent(Graphics g) {
gFG.setComposite(composite);
gFG.drawImage(bg, 0, 0, null);
gFG.setPaintMode();
gFG.setColor(Color.RED);
gFG.fillOval(++x, ++y, size, size);
gBuffer.drawImage(fg, 0, 0, w, h, null);
g.drawImage(buffer, 0, 0, w, h, null);
if (x > w) {
x = 0;
y = 0;
}
}
public static void main(String[] args) {
JFrame f = new JFrame("Fade Test");
FadeComponent fc = new FadeComponent();
f.getContentPane().add(fc);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
--
Andrey Kuznetsov
http://uio.imagero.com Unified I/O for Java
http://reader.imagero.com Java image reader
http://jgui.imagero.com Java GUI components and utilities
Thank you, thank you, thank you. That is exactly as
I imagined it.
Once more you've come through for me, Andrey.. :-)
Andrew T.
Graphics gFG = fg.getGraphics(); // I changed this to fg?
gFG.setColor(Color.RED);
gFG.fillOval(x,y,size,size);
buffer = new BufferedImage(
w, h, BufferedImage.TYPE_INT_ARGB );
Thread t = new Thread(this);
t.start();
}
public void run() {
while(true) {
repaint();
try {
Thread.sleep(40);
} catch(InterruptedException ie) {
// continue..
}
}
}
public Dimension getPreferredSize() {
return new Dimension(300,300);
}
public void paintComponent(Graphics g) {
Graphics gBuffer = buffer.getGraphics();
gBuffer.drawImage( bg,0,0,w,h,null );
Graphics2D gFG = (Graphics2D)fg.getGraphics();
gFG.setColor(new Color(255,255,255,10)); // can be 0,0,0,10
gFG.fillRect(0,0,w,h);
gFG.setColor(Color.RED);
gFG.fillOval(++x,++y,size,size);
gBuffer.setColor(new Color(255,255,255,10)); // can be 0,0,0,10
gBuffer.setXORMode(new Color(255,255,255,0));
gBuffer.drawImage( fg,0,0,w,h,null );
gBuffer.setPaintMode();
g.drawImage( buffer,0,0,w,h,null );
if (x>w) {
x=0;
y=0;
}
}
public static void main(String[] args) {
JFrame f = new JFrame( "Fade Test" );
FadeComponent fc = new FadeComponent();
f.getContentPane().add(fc);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
--
Knute Johnson
email s/nospam/knute/
Yeah! (chuckles) that's one solution.
Unfortunately - the actual situation I need it for is
a 'Milky Way' background with 'Zooming Stars'
in the foreground. It just doesn't quite work for
me if the milky way is on top!
Andrey pointed me in the right direction with the
AlphaComposite.
Thanks for your response.
Andrew T.
> Once more you've come through for me, Andrey.. :-)
;-)
Andrey
--
It's around 100Kb (waggles hand) to get it on-screen,
unless you're using Java <1.5 (sorry, the underlying
SaverBeans API is 1.5+).
Andrew T.
just 2 notes:
1) you forgot to exit application on frame closure
2) after frame resizing the animation is brocken, so you can
i) make frame unresizable or
ii) do some reset after resizing
* I'll have to fix that.**
> 2) after frame resizing the animation is brocken, so you can
> i) make frame unresizable or
Aaaah.. yes.
* The ScreensaverFrame (part of the SaverBeans API),
was intended originally as a component that was purely
for testing Screensavers during development.
As its role has expanded into the WebStart previews,
it has had to undergo a number of changes.
One more change it needs is to allow the frame size
to be locked, ...
> ii) do some reset after resizing
..as screensavers themselves never have to deal with
the screen changing size - so many (including
StarZoom) don't.
** The ScreensaverFrame is part of the SaverBeans API,
(an incubator project at JDIC) but the person making
(or suggesting) the most changes to it, is me.
The version shown in that preview is already heavily
modified from the version in the standard API.
Andrew T.