Name: jl125535 Date: 02/24/2004
A DESCRIPTION OF THE REQUEST :
Currently lightweight components property "opaque" determines wether the background of component is going to be painted. If it is set to true the background of the component is filled with background color and the components behind it are not repainted.
If you set it to false the background is not painted and components behind the current component are redrawn. This results in completely transparent component.
The idea is to have components (especially JInternalFrame, JPanel,... well all of them) partially transparent by setting background color to new Color(red, green, blue, alpha).
If you do this now you have to set opaque property to true which results in wrong repaint as components behind this component are not repainted.
Also in some components in pluggable look'n'feel code there are statements like setOpaque(true) (BasicInternalFrameUI method installUI(...)) which should not be there (it is up to the programmer to decide if his component is going to be opaque or not)
The solution (a beginning of the solution) would be to change some Swing code
new update method in javax.swing.plaf.ComponentUI should look like
public void update(Graphics g, JComponent c) {
if (c.isOpaque() || c.getBackground().getAlpha() != 0) {
g.setColor(c.getBackground());
g.fillRect(0, 0, c.getWidth(),c.getHeight());
}
paint(g, c);
}
and also in JComponent (to prevent painting components that didn't have setBackground() called) If you have 5 panels on top of each other and you only explicitly set background color for the lowest one the old code would return the parent's color for each of them thus painting with same semi-transparent color 5 times (which results in reduced transparency)
javax.swing.JComponent:
Color swingBackground;
public Color getBackground() {
Color c = super.getBackground();
if (!isOpaque()) {
return swingBackground == null ? new Color(0,0,0,0) : swingBackground;
}
return c;
}
this actually already solves most of the problems. There are still some things to be done for making ScrollBars transparent... but this already gives very nice results.
Also JFrame, JWindow transparency would be nice. Most operating systems supports it. And in case if some doesn't you can always ignore the setting and display opaque window. It is really time Java gets this nice feature...
JUSTIFICATION :
Much better looking user interfaces :-)
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Background of component is painted if background color alpha channel <> 0 even if opaque property is set to false.
ACTUAL -
Background is only painted if opaque property is set to true. Otherwise component is completely transparent.
---------- BEGIN SOURCE ----------
package transparency;
import javax.swing.*;
import java.awt.*;
/**
* Put couple of this frames in JDesktopPane and play with
* them before and after suggested changes
* also setOpaque should be propagated to contentPane for JInternalFrame
* and to viewport for JScrollPane...
*/
public class TransparentFrame1 extends JInternalFrame {
BorderLayout borderLayout1 = new BorderLayout();
JScrollPane jScrollPane1 = new JScrollPane();
JButton jButton1 = new JButton();
JTextPane jTextPane1 = new JTextPane();
public TransparentFrame1() {
try {
jbInit();
}
catch(Exception ex) {
ex.printStackTrace();
}
}
void jbInit() throws Exception {
this.getContentPane().setLayout(borderLayout1);
jButton1.setBackground(new Color(255,0,0,128));
jButton1.setOpaque(false);
jButton1.setSelected(false);
jButton1.setText("jButton1");
jTextPane1.setOpaque(false);
jTextPane1.setText("jTextPane1");
jScrollPane1.setOpaque(false);
this.getContentPane().setBackground(new Color(0, 255, 138,128));
((JPanel)this.getContentPane()).setOpaque(false);
this.getContentPane().add(jScrollPane1, BorderLayout.CENTER);
jScrollPane1.getViewport().setOpaque(false);
jScrollPane1.getViewport().add(jTextPane1, null);
this.getContentPane().add(jButton1, BorderLayout.NORTH);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Writing look and feel based on existing one and overriding problematic code. Quite easy actually but the problem with Component.getBackground can't be solved in this way.
Also it's much more elegant to solve this in ComponentUI...
(Incident Review ID: 240015)
======================================================================