I've been trying to get this right for days, read so many explanations but as literally as I try to apply them, nothing seems to work.
What I need to do is create a custom shaped window. The way I want to do it is by setting the window background to an image like this one:
The method I'm using to try to accomplish this is, in general lines, the one described here https://stackoverflow.com/a/13594794/1387451
But it doesn't quite work. Instead, it looks like if java was interpreting my background as an alpha mask: White becomes opaque and black transparent. I think it's pretty awesome that java can do that, but it's not what I need.
I tried playing with the opacity of my JFrame
's content pane. Nothing.
I tried using a JLabel
or a JPanel
for the image to no avail.
Please, help me decipher this.
Here's the relevant code.
The JFrame
:
public class LectorWindow extends JFrame {
public LectorWindow() {
Dimension winSize = new Dimension(440, 80);
LectorDraggerListener dragger = new LectorDraggerListener(this);
addMouseListener(dragger);
addMouseMotionListener(dragger);
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
ex.printStackTrace();
}
setUndecorated(true);
setBackground(new Color(0f, 0f, 0f, 0f));
setContentPane(new TransparentContentPane());
setSize(winSize);
int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;
setLocation(screenWidth/2 - getWidth()/2, 0);
setLayout(new BorderLayout());
JPanel background = new BackgroundPanel();
background.setLayout(new BoxLayout(background, BoxLayout.X_AXIS));
add(background);
setResizable(false);
setAlwaysOnTop(true);
setUpSysTray();
setVisible(true);
}
}
The ContentPane:
public class TransparentContentPane extends JPanel {
private static final long serialVersionUID = -386560825154911212L;
public TransparentContentPane() {
setOpaque(false);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(0, 0, getWidth(), getHeight());
}
}
And the background image JPanel
:
public final class BackgroundPanel extends JPanel {
private static final long serialVersionUID = -5526340149401796784L;
private BufferedImage background;
public BackgroundPanel() {
try {
background = ImageIO.read(BackgroundPanel.class.getResource("/lector/resources/background.png"));
} catch (IOException e) {
e.printStackTrace();
}
setOpaque(false);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(background.getWidth(), background.getHeight());
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g2d.drawImage(background, x, y, this);
g2d.dispose();
}
}
}
I'm using OpenJDK on XFCE with window Compositing enabled. (I tried disabling it but then it all gets even weirder). I want this to work on Java 7, I don't care about 6.
Here are two screenshots of my program doing it's thing:
With the ContentPane painted in red.
With the ContentPane being just a normal JPanel
with setOpaque(false)
.
(Why are we painting that red anyway?)