Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 481
Jay Gridley Avatar asked Jan 17 '23 19:01

Jay Gridley


2 Answers

To make JFrame with a custom transparent border you have to change frame's opacity first:

frame.setUndecorated ( true );
AWTUtilities.setWindowOpaque ( frame, false );

After that your frame will not have any system border and background at all, so you can paint something transparent (for e.g. a border). By the way, the component which border you change must be non-opaque aswell as the containers under the component to let the pixels behind the frame "come through".

Also you can make the whole frame semi-transparent in some cases:

AWTUtilities.setWindowOpacity ( frame, 0.5f );

This will make it 50% transparent (and it works even with system window decoration).

Though those features are properly supported only on Win and Mac OS systems yet.

like image 132
Mikle Garin Avatar answered Jan 25 '23 10:01

Mikle Garin


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);
    }
}
like image 23
Guillaume Polet Avatar answered Jan 25 '23 08:01

Guillaume Polet