JDK-5001982 : Partial transparency of lightweight components
  • Type: Enhancement
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.4.2
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2004-02-24
  • Updated: 2017-05-23
Related Reports
Relates :  
Relates :  
Description

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) 
======================================================================

Comments
EVALUATION Contribution forum : https://jdk-collaboration.dev.java.net/servlets/ProjectForumMessageView?forumID=1463&messageID=15084
28-08-2006

EVALUATION I disagree with the submitter regarding the meaning of the opaque property. While it is true that in most cases a component with opaque==true will have its background painted (and vice versa) that is not the true meaning of the opaque property. The opaque property was designed to indicate to the RepaintManager that it can optimize painting by not needing to paint what lies behind the component. Unfortunately, the meaning of the opaque property has become overloaded. I also disagree with the submitter where they say the UI's shouldn't be using opaque. The opaque property was designed to specifically be used by those implementing components. It was NOT designed for the programmer to turn on and off background painting. Components should provide other methods for this (for example, button's setContentAreaFilled). Again, the meaning of opaque property has become overloaded. Regardless of what I've mentioned above, this issue has come up in discussion. It would be nice to provide a mechanism by which developers can have their components be translucent. I'll therefore be keeping this bug open to track the issue. With respect the submitter's request for support for top-level window tranparency, that issue has been requested under another bug (4479178). ###@###.### 2004-03-22
22-03-2004