Hi,
I’m having troubles figuring to which extent full translucency (down to
the desktop background) is supported by Swing. Behaviors are not the
same depending on the component used (light or heavy), the JDK, as well
as the graphics card. For instance, why the following simple example
requires a JDK > 8?
Using a newer JDK, things mostly work fine (on Linux). I’ve got
flickering issues, but my main problem is that setting the
"sun.java2d.opengl" breaks everything. It seems like the underlying FBO
created don’t have any alpha channel at all. The final texture used by
the desktop compositor is not alpha-premultiplied and have a global 0.0
or 1.0 alpha value (I’ve seen both cases). However, I didn’t found any
known issue describing this basic problem. Am I missing something
obvious in my code here?
- Florent
// Start of code
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsDevice.WindowTranslucency;
import java.awt.Rectangle;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.WindowConstants;
import javax.swing.border.EmptyBorder;
public class SimpleTranslucentFrame {
@SuppressWarnings("serial")
public static void main(String[] args) {
String openglPropertyName = "sun.java2d.opengl";
JLabel openglLabel = new JLabel(openglPropertyName + "=" +
System.getProperty(openglPropertyName, "false"));
JLabel swingLabel = new JLabel("Swing");
swingLabel.setFont(swingLabel.getFont().deriveFont(48f));
new Timer(500, e -> swingLabel.setText(new
StringBuilder(swingLabel.getText()).reverse().toString())).start();
JButton closeButton = new JButton("Fermer");
closeButton.addActionListener(event -> System.exit(0));
JPanel panel = new JPanel(new BorderLayout(10, 10));
panel.setBorder(new EmptyBorder(10, 10, 10, 10));
panel.setOpaque(false);
panel.add(openglLabel, BorderLayout.NORTH);
panel.add(swingLabel);
panel.add(closeButton, BorderLayout.SOUTH);
// Required custom content pane (a JDK > 8 is also required).
JPanel contentPane = new JPanel(new BorderLayout()) {
@Override
public void paint(Graphics g) {
((Graphics2D) g).setBackground(getBackground());
Rectangle clipBounds = g.getClipBounds();
g.clearRect(clipBounds.x, clipBounds.y,
clipBounds.width, clipBounds.height);
super.paint(g);
}
};
contentPane.setBackground(new Color(0, 0, 0, 0));
contentPane.setOpaque(false);
JFrame frame = new JFrame();
GraphicsDevice device=frame.getGraphicsConfiguration().getDevice();
// Fun fact: PERPIXEL_TRANSLUCENT =/=> TRANSLUCENT (with a
Nvidia Quadro 4000)
assert
device.isWindowTranslucencySupported(WindowTranslucency.PERPIXEL_TRANSLUCENT);
frame.setUndecorated(true);
frame.setBackground(new Color(0, 0, 0, 0));
frame.setContentPane(contentPane);
frame.add(panel);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
// End of code