Search code examples
javaswingtransparencyjinternalframe

make whole jinternalframe transparent


Right now I am making my jinternal frames transparent using this code:

double rgbConversionBackpack = Double.parseDouble(MyClient.configFile.getProperty("BACKPACK_FRAME_ALPHA"));
double tmp = (rgbConversionBackpack / 100.0) * 255.0;
this.getContentPane().setBackground(new Color(140, 0, 0, (int)tmp));
this.setOpaque(false);

I have code on the sliders to set the alpha which all works perfectly and saves it to a properties file, yada, yada, yada. The question is how do I make the entire JInternal Frame transparent.

Right now I have only be able to set the content pane, and any other panels (etc) that are in the jinternal frames transparent, but I want to make the entire JinternalFrame(borders and all) transparent.

Screenshot below shows how on the backpack the red tinted are is partially transparent and looks decent, but still want the border to be transparent also.

enter image description here

Is there a way to override the draw super method for each of my classes the extend JInternalFrame to have it draw semi transparent(depending on value obviously)?


Solution

  • You could do this by changing the AlphaComposite that the JInternalFrame's paint method uses. You have to be careful though to repaint the containing top level window at the location of the transparent component lest you have funny side effects. For example:

    import java.awt.*;
    import javax.swing.*;
    import javax.swing.event.ChangeEvent;
    import javax.swing.event.ChangeListener;
    
    @SuppressWarnings("serial")
    public class TransparentInternalFrame extends JDesktopPane {
       private static final Color COLOR_1 = Color.red;
       private static final Color COLOR_2 = Color.blue;
       private static final float PT_2 = 30f;
       private static final int PREF_W = 800;
       private static final int PREF_H = 500;
    
       public TransparentInternalFrame() {
          add(new MyInternalFrame("Foo", 50, 50, 300, 300, 0.2f));
          add(new MyInternalFrame("Foo", 400, 100, 300, 300, 0.4f));
       }
    
       @Override
       protected void paintComponent(Graphics g) {
          super.paintComponent(g);
          Graphics2D g2 = (Graphics2D) g;
          g2.setPaint(new GradientPaint(0, 0, COLOR_1, PT_2, PT_2, COLOR_2, true));
          g2.fillRect(0, 0, getWidth(), getHeight());
       }
    
       @Override
       public Dimension getPreferredSize() {
          return new Dimension(PREF_W, PREF_H);
       }
    
       private static void createAndShowGui() {
          TransparentInternalFrame mainPanel = new TransparentInternalFrame();
    
          JFrame frame = new JFrame("TransparentInternalFrame");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.getContentPane().add(mainPanel);
          frame.pack();
          frame.setLocationByPlatform(true);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGui();
             }
          });
       }
    }
    
    @SuppressWarnings("serial")
    class MyInternalFrame extends JInternalFrame {
       private AlphaComposite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
    
       public MyInternalFrame(String title, int x, int y, int w, int h, final float alpha) {
          super(title);
          setClosable(true);
          setBounds(x, y, w, h);
          setVisible(true);
    
          int sliderValue = (int) (alpha * 100);
          comp = comp.derive(alpha);
          final JSlider slider = new JSlider(0, 100, sliderValue);
          slider.setMajorTickSpacing(20);
          slider.setMinorTickSpacing(5);
          slider.setPaintLabels(true);
          slider.setPaintTicks(true);
          slider.setBorder(BorderFactory.createTitledBorder("Alpha Value"));
          slider.addChangeListener(new ChangeListener() {
    
             @Override
             public void stateChanged(ChangeEvent cEvt) {
                float alpha = (float) slider.getValue() / 100f;
                setAlpha(alpha);
                MyInternalFrame.this.repaint();
    
                Window win = SwingUtilities.getWindowAncestor(MyInternalFrame.this);
                win.repaint();
             }
          });
    
          add(new JLabel("My Label", SwingConstants.CENTER));
          add(slider, BorderLayout.SOUTH);
       }
    
       @Override
       public void paint(Graphics g) {
          Graphics2D g2 = (Graphics2D) g;
          g2.setComposite(comp);
          super.paint(g);
       }
    
       public void setAlpha(float alpha) {
          comp = comp.derive(alpha);
       }
    }
    

    AlphaComposite Demo

    But note that this program is not fully fixed. You'll still see pixel errors if you drag one JInternalFrame over another. I still need to work the bugs out...