问题
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?
Thanks!
回答1:
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);
}
}
回答2:
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.
来源:https://stackoverflow.com/questions/10409500/translucent-jframe-border