you have probably seen this before, it is another screenshot-based implementation of a translucent window. (is there any other way besides JNI? if so, this is news to me.)
some things to note about it:
- initialises with a string for the window image(found using getClass().getResource() on it)
- it doesn’t refresh its background, except when being dragged, and even then, it only grabs a shot of the area it is moving into. good, because the window never flickers bad because the background more easily gets out of sync if you never move it.
- you can put ordinary components onto its ContentPane
- uses double buffering so should be very flicker-free.
- performance is better with GIF images than PNG images. (ie, transparency is much faster than translucency)
- for best results, use with setUndecorated(true) to hide the JFrame’s window decorations.
a picture is worth a thousand words as they say:
http://juddman.googlepages.com/bgw-example.png
here is the class file:
BackgroundWindow.java
import java.awt.*;
import javax.swing.*;
import java.awt.image.*;
import javax.imageio.*;
import java.awt.event.*;
class InvisiblePanel extends JPanel
{
public void paint(Graphics g)
{
paintChildren(g);
}
}
public class BackgroundWindow extends JFrame implements MouseListener, MouseMotionListener
{
final int delay = 1;
int x, y, w, h,
oldX, oldY,
mouseX = 0,
mouseY = 0;
long time;
BufferedImage image,
bgImage,
bgBuffer,
windowBuffer,
nativeImage;
Robot rob;
public BackgroundWindow(String picture)
{
x = 0; y = 0;
try{
image = ImageIO.read(getClass().getResource(picture));
} catch (Throwable e) {image = null;}
w = image.getWidth();
h = image.getHeight();
setSize(w, h);
addMouseListener(this);
addMouseMotionListener(this);
setContentPane(new InvisiblePanel());
}
public void paint(Graphics windowGraphics)
{
if(nativeImage == null || bgImage == null) {
nativeImage = getGraphicsConfiguration().createCompatibleImage(w, h);
windowBuffer = getGraphicsConfiguration().createCompatibleImage(w, h);
setVisible(false);
try{
Thread.sleep(100);
rob = new Robot(getGraphicsConfiguration().getDevice());
}
catch(Exception e) {System.exit(1);}
bgImage = rob.createScreenCapture(new Rectangle(x, y, w, h));
bgBuffer = rob.createScreenCapture(new Rectangle(x, y, w, h));
setVisible(true);
}
Graphics g = windowBuffer.getGraphics();
nativeImage.getGraphics().drawImage(bgImage, 0, 0, this);
nativeImage.getGraphics().drawImage(image, 0, 0, this);
g.drawImage(nativeImage, 0, 0, this);
getContentPane().paint(g);
windowGraphics.drawImage(windowBuffer, 0, 0, this);
}
public void repaint()
{
bgImage = null;
super.repaint();
}
public void setLocation(int newX, int newY)
{
if(bgBuffer != null) {
int dx = newX - x;
int dy = newY - y;
//first, copy background image onto iteslf displaced.
bgBuffer.getGraphics().drawImage(bgImage, -dx, -dy, this);
//second, copy new region into background...
if(dx > 0) {
int my = dy;
if(my < 0) my = -my;
Rectangle r = new Rectangle(x + w, y-my, dx, h+my*2);
Image strip = rob.createScreenCapture(r);
bgBuffer.getGraphics().drawImage(strip, w-dx, -dy-my, this);
}
else if(dx < 0) {
int my = dy;
if(my < 0) my = -my;
Rectangle r = new Rectangle(x+dx, y-my, -dx, h+my*2);
Image strip = rob.createScreenCapture(r);
bgBuffer.getGraphics().drawImage(strip, 0, -dy-my, this);
}
if(dy > 0) {
Rectangle r = new Rectangle(x, y+h, w, dy);
Image strip = rob.createScreenCapture(r);
bgBuffer.getGraphics().drawImage(strip, -dx, h-dy, this);
}
else if(dy < 0) {
Rectangle r = new Rectangle(x, y+dy, w, -dy);
Image strip = rob.createScreenCapture(r);
bgBuffer.getGraphics().drawImage(strip, -dx, 0, this);
}
//finally, put bgBuffer back to bgImage.
bgImage.getGraphics().drawImage(bgBuffer, 0, 0, this);
this.x = newX;
this.y = newY;
paint(getGraphics());
}
super.setLocation(x, y);
pause(1); //stops jitter
}
public void mousePressed(MouseEvent e){mouseX = e.getX(); mouseY = e.getY();}
public void mouseReleased(MouseEvent e){mouseX = e.getX(); mouseY = e.getY();}
public void mouseClicked(MouseEvent e){mouseX = e.getX(); mouseY = e.getY();}
public void mouseEntered(MouseEvent e){mouseX = e.getX(); mouseY = e.getY();}
public void mouseExited(MouseEvent e){mouseX = e.getX(); mouseY = e.getY();}
//for dragging the window by any blank area
public void mouseDragged(MouseEvent e){
//first, calculate the distance moved...
long now = System.currentTimeMillis();
if(now - time < delay) return;
time = now;
int dx = e.getX() - mouseX;
int dy = e.getY() - mouseY;
setLocation(x + dx, y + dy);
mouseX = e.getX() - dx; mouseY = e.getY() - dy;
}
public void mouseMoved(MouseEvent e){}
static void pause(long time) {
try{ Thread.sleep(time);}
catch(Exception e){}
}
}
and here’s how i used it in the screenshot above:
import java.awt.*;
import javax.swing.*;
import java.awt.image.*;
public class Demo
{
public static void main(String[] args)
{
JFrame mainFrame = new BackgroundWindow("winda.png");
mainFrame.setUndecorated(true);
JPanel cp = (JPanel)mainFrame.getContentPane();
cp.setLayout(null);
JButton b = new JButton("Hi there!");
b.setLocation(130,10);
b.setSize(100,30);
cp.add(b);
JTextArea text = new JTextArea("this doesnt work quite right.");
text.setFont(new Font("Arial", Font.BOLD, 14));
text.setForeground(Color.blue);
text.setLineWrap(true); //line wrapping
text.setWrapStyleWord(true); //wrap on end of words.
JScrollPane scroll = new JScrollPane(text);
scroll.setSize(300,70);
scroll.setLocation(40, 70);
cp.add(scroll);
mainFrame.setVisible(true);
}
}