Search code examples
javaswinguser-interfacebordertranslucency

Translucent JFrame border


I want make JFrame border transparent, so I am trying to do so using my own Border class...

private class ShadowBorder extends AbstractBorder {

    private static final int RADIUS = 30;

    @Override
    public boolean isBorderOpaque() {
        return false;
    }

    @Override
    public Insets getBorderInsets(Component c) {
        return new Insets(RADIUS, RADIUS, RADIUS, RADIUS);
    }

    @Override
    public Insets getBorderInsets(Component c, Insets insets) {
        insets.top = RADIUS;
        insets.left = RADIUS;
        insets.bottom = RADIUS;
        insets.right = RADIUS;
        return insets;
    }

    @Override
    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                 RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setColor(new Color(0x66000000, true));

            g2d.fillRect(0, 0, width - RADIUS, RADIUS);
        }
}

but border is not transparent in final. There is also white background inside of border, but I do not know why (see atach. image). Any ideas?

enter image description here

Thanks!


Solution

  • You need to set the window as not opaque and use a composite on the Graphics. Also, in your code, you are only printing one border, not the four of them, this is why you see only one border painted. Something like this should do it (although it would be better to paint the borders based on the insets, not your RADIUS constant):

    import java.awt.AlphaComposite;
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Insets;
    import java.awt.RenderingHints;
    import java.io.UnsupportedEncodingException;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.border.AbstractBorder;
    
    import com.sun.awt.AWTUtilities;
    
    public class Main {
    
        private static class ShadowBorder extends AbstractBorder {
    
            private static final int RADIUS = 30;
    
            @Override
            public boolean isBorderOpaque() {
                return false;
            }
    
            @Override
            public Insets getBorderInsets(Component c) {
                return new Insets(RADIUS, RADIUS, RADIUS, RADIUS);
            }
    
            @Override
            public Insets getBorderInsets(Component c, Insets insets) {
                insets.top = RADIUS;
                insets.left = RADIUS;
                insets.bottom = RADIUS;
                insets.right = RADIUS;
                return insets;
            }
    
            @Override
            public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2d.setColor(new Color(66, 0, 0));
                g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_ATOP, 0.5f));
                g2d.fillRect(0, 0, width - RADIUS, RADIUS);
                g2d.fillRect(width - RADIUS, 0, RADIUS, height - RADIUS);
                g2d.fillRect(0, RADIUS, RADIUS, height - RADIUS);
                g2d.fillRect(RADIUS, height - RADIUS, width - RADIUS, RADIUS);
            }
        }
    
        public static void main(String[] args) throws UnsupportedEncodingException {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setUndecorated(true);
            AWTUtilities.setWindowOpaque(frame, false);
            JPanel panel = new JPanel(new BorderLayout());
            JButton button = new JButton("Hello");
            panel.add(button);
            panel.setBorder(new ShadowBorder());
            frame.setContentPane(panel);
            frame.setSize(300, 200);
            frame.setVisible(true);
        }
    }