与圆angular和透明度的边界

以下屏幕截图显示了TextBubbleBorder 1的testing。 我想使矩形外部的组件angular落完全透明,并显示其下的任何组件。 通过在Graphics2D实例上设置Clip (表示圆angular外的区域)并调用clearRect()我find了一种方法来将标签的BG颜色限制为“在边框内”。 这可以在Label 1看到。

边界测试

但是,如果父面板上有红色的BG(或任何非标准颜色),则可以看到这种方法的不足之处。 angular落默认为默认的面板颜色(最容易看到Panel 2 )。

最终,我希望能够在父容器中使用非标准的颜色,但部分原因是我需要做什么才能使用渐变颜料复制此组件?

有谁知道让angular落变得透明的方法吗?

 import java.awt.*; import java.awt.geom.*; import javax.swing.*; import javax.swing.border.*; public class BorderTest { public static void main(String[] args) { Runnable r = new Runnable() { @Override public void run() { JPanel gui = new JPanel(new GridLayout(1,0,5,5)); gui.setBorder(new EmptyBorder(10,10,10,10)); gui.setBackground(Color.RED); AbstractBorder brdr = new TextBubbleBorder(Color.BLACK,2,16,0); JLabel l1 = new JLabel("Label 1"); l1.setBorder(brdr); gui.add(l1); JLabel l2 = new JLabel("Label 2"); l2.setBorder(brdr); l2.setBackground(Color.YELLOW); l2.setOpaque(true); gui.add(l2); JPanel p1 = new JPanel(); p1.add(new JLabel("Panel 1")); p1.setBorder(brdr); p1.setOpaque(false); gui.add(p1); JPanel p2 = new JPanel(); p2.add(new JLabel("Panel 2")); p2.setBorder(brdr); gui.add(p2); JOptionPane.showMessageDialog(null, gui); } }; // Swing GUIs should be created and updated on the EDT // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html SwingUtilities.invokeLater(r); } } class TextBubbleBorder extends AbstractBorder { private Color color; private int thickness = 4; private int radii = 8; private int pointerSize = 7; private Insets insets = null; private BasicStroke stroke = null; private int strokePad; private int pointerPad = 4; RenderingHints hints; TextBubbleBorder( Color color) { new TextBubbleBorder(color, 4, 8, 7); } TextBubbleBorder( Color color, int thickness, int radii, int pointerSize) { this.thickness = thickness; this.radii = radii; this.pointerSize = pointerSize; this.color = color; stroke = new BasicStroke(thickness); strokePad = thickness / 2; hints = new RenderingHints( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); int pad = radii + strokePad; int bottomPad = pad + pointerSize + strokePad; insets = new Insets(pad, pad, bottomPad, pad); } @Override public Insets getBorderInsets(Component c) { return insets; } @Override public Insets getBorderInsets(Component c, Insets insets) { return getBorderInsets(c); } @Override public void paintBorder( Component c, Graphics g, int x, int y, int width, int height) { Graphics2D g2 = (Graphics2D) g; int bottomLineY = height - thickness - pointerSize; RoundRectangle2D.Double bubble = new RoundRectangle2D.Double( 0 + strokePad, 0 + strokePad, width - thickness, bottomLineY, radii, radii); Polygon pointer = new Polygon(); // left point pointer.addPoint( strokePad + radii + pointerPad, bottomLineY); // right point pointer.addPoint( strokePad + radii + pointerPad + pointerSize, bottomLineY); // bottom point pointer.addPoint( strokePad + radii + pointerPad + (pointerSize / 2), height - strokePad); Area area = new Area(bubble); area.add(new Area(pointer)); g2.setRenderingHints(hints); Area spareSpace = new Area(new Rectangle(0, 0, width, height)); spareSpace.subtract(area); g2.setClip(spareSpace); g2.clearRect(0, 0, width, height); g2.setClip(null); g2.setColor(color); g2.setStroke(stroke); g2.draw(area); } } 
  1. 虽然TextBubbleBorder被devise为内部填充JTextArea与背景图像 (由于上述原因,由于文本区域是一个混乱,结束了使用JLabel ),通过指定一个pointerSize为0,我们结束了一个'圆angular的矩形' 。

注意这个代码中有一个剪切错误,在paintComponent()的可接受的答案中正在绘制其他组件 。 如果“修剪错误修复”被合并,这应该只被视为一个解决scheme。


 // Paint the BG color of the parent, everywhere outside the clip // of the text bubble. 

在正确显示的源代码中查看这一点:

带有0px语音指针的BorderTest

带有16px语音指针的BorderTest

 import java.awt.*; import java.awt.image.*; import java.awt.geom.*; import javax.swing.*; import javax.swing.border.*; public class BorderTest { public static void main(String[] args) { Runnable r = new Runnable() { @Override public void run() { JPanel gui = new JPanel(new GridLayout(2,0,5,5)); gui.setBorder(new EmptyBorder(10,10,10,10)); gui.setBackground(Color.RED); AbstractBorder brdrLeft = new TextBubbleBorder(Color.BLACK,2,16,16); AbstractBorder brdrRight = new TextBubbleBorder(Color.BLACK,2,16,16,false); JLabel l1 = new JLabel("Label 1"); l1.setBorder(brdrRight); gui.add(l1); JLabel l2 = new JLabel("Label 2"); l2.setBorder(brdrLeft); l2.setBackground(Color.YELLOW); l2.setOpaque(true); gui.add(l2); JPanel p1 = new JPanel(); p1.add(new JLabel("Panel 1")); p1.setBorder(brdrRight); p1.setOpaque(false); gui.add(p1); JPanel p2 = new JPanel(); p2.add(new JLabel("Panel 2")); p2.setBorder(brdrLeft); gui.add(p2); JOptionPane.showMessageDialog(null, gui); } }; // Swing GUIs should be created and updated on the EDT // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html SwingUtilities.invokeLater(r); } } class TextBubbleBorder extends AbstractBorder { private Color color; private int thickness = 4; private int radii = 8; private int pointerSize = 7; private Insets insets = null; private BasicStroke stroke = null; private int strokePad; private int pointerPad = 4; private boolean left = true; RenderingHints hints; TextBubbleBorder( Color color) { this(color, 4, 8, 7); } TextBubbleBorder( Color color, int thickness, int radii, int pointerSize) { this.thickness = thickness; this.radii = radii; this.pointerSize = pointerSize; this.color = color; stroke = new BasicStroke(thickness); strokePad = thickness / 2; hints = new RenderingHints( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); int pad = radii + strokePad; int bottomPad = pad + pointerSize + strokePad; insets = new Insets(pad, pad, bottomPad, pad); } TextBubbleBorder( Color color, int thickness, int radii, int pointerSize, boolean left) { this(color, thickness, radii, pointerSize); this.left = left; } @Override public Insets getBorderInsets(Component c) { return insets; } @Override public Insets getBorderInsets(Component c, Insets insets) { return getBorderInsets(c); } @Override public void paintBorder( Component c, Graphics g, int x, int y, int width, int height) { Graphics2D g2 = (Graphics2D) g; int bottomLineY = height - thickness - pointerSize; RoundRectangle2D.Double bubble = new RoundRectangle2D.Double( 0 + strokePad, 0 + strokePad, width - thickness, bottomLineY, radii, radii); Polygon pointer = new Polygon(); if (left) { // left point pointer.addPoint( strokePad + radii + pointerPad, bottomLineY); // right point pointer.addPoint( strokePad + radii + pointerPad + pointerSize, bottomLineY); // bottom point pointer.addPoint( strokePad + radii + pointerPad + (pointerSize / 2), height - strokePad); } else { // left point pointer.addPoint( width - (strokePad + radii + pointerPad), bottomLineY); // right point pointer.addPoint( width - (strokePad + radii + pointerPad + pointerSize), bottomLineY); // bottom point pointer.addPoint( width - (strokePad + radii + pointerPad + (pointerSize / 2)), height - strokePad); } Area area = new Area(bubble); area.add(new Area(pointer)); g2.setRenderingHints(hints); // Paint the BG color of the parent, everywhere outside the clip // of the text bubble. Component parent = c.getParent(); if (parent!=null) { Color bg = parent.getBackground(); Rectangle rect = new Rectangle(0,0,width, height); Area borderRegion = new Area(rect); borderRegion.subtract(area); g2.setClip(borderRegion); g2.setColor(bg); g2.fillRect(0, 0, width, height); g2.setClip(null); } g2.setColor(color); g2.setStroke(stroke); g2.draw(area); } } 

尝试这个:

  JPanel p = new JPanel() { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Dimension arcs = new Dimension(15,15); //Border corners arcs {width,height}, change this to whatever you want int width = getWidth(); int height = getHeight(); Graphics2D graphics = (Graphics2D) g; graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); //Draws the rounded panel with borders. graphics.setColor(getBackground()); graphics.fillRoundRect(0, 0, width-1, height-1, arcs.width, arcs.height);//paint background graphics.setColor(getForeground()); graphics.drawRoundRect(0, 0, width-1, height-1, arcs.width, arcs.height);//paint border } }; 

用我的testing:

  JFrame f = new JFrame(); f.setLayout(null); f.setDefaultCloseOperation(3); f.setSize(500, 500); JPanel p = new JPanel() { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Dimension arcs = new Dimension(15,15); int width = getWidth(); int height = getHeight(); Graphics2D graphics = (Graphics2D) g; graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); //Draws the rounded opaque panel with borders. graphics.setColor(getBackground()); graphics.fillRoundRect(0, 0, width-1, height-1, arcs.width, arcs.height);//paint background graphics.setColor(getForeground()); graphics.drawRoundRect(0, 0, width-1, height-1, arcs.width, arcs.height);//paint border } }; p.setBounds(10,10,100,30); p.setOpaque(false); f.getContentPane().setBackground(Color.red); f.add(p); f.show(); 

结果是:

代码结果

谢谢@BackSlash,很好,很简单。 我扩展了这个,所以它更可重用。 这也允许在构造函数中设置背景颜色。 而且我展示了如何制作一个圆形面板以获得乐趣。

在这里输入图像描述

 import java.awt.*; import javax.swing.*; public class RoundedPanelExample extends JFrame { public RoundedPanelExample() { setDefaultCloseOperation(EXIT_ON_CLOSE); setTitle("Rounded Panel Example"); setResizable(true); setDefaultLookAndFeelDecorated(true); setSize(500, 500); Container pane = getContentPane(); pane.setLayout(null); pane.setBackground(Color.LIGHT_GRAY); JPanel p1 = new RoundedPanel(10, Color.CYAN); p1.setBounds(10,10,100,60); p1.setOpaque(false); pane.add(p1); JPanel p2 = new RoundedPanel(15, Color.RED); p2.setBounds(150,10,50,50); p2.setOpaque(false); pane.add(p2); JPanel p3 = new RoundedPanel(30); p3.setBounds(230,10,100,150); p3.setOpaque(false); pane.add(p3); JPanel p4 = new RoundedPanel(20); p4.setBounds(10,200,100,100); p4.setBackground(Color.GREEN); p4.setOpaque(false); pane.add(p4); JPanel p5 = new RoundedPanel(200); p5.setBounds(150,200,200,200); p5.setBackground(Color.BLUE); p5.setOpaque(false); pane.add(p5); } public static void main(String[] args) { RoundedPanelExample gui = new RoundedPanelExample(); gui.setVisible(true); } class RoundedPanel extends JPanel { private Color backgroundColor; private int cornerRadius = 15; public RoundedPanel(LayoutManager layout, int radius) { super(layout); cornerRadius = radius; } public RoundedPanel(LayoutManager layout, int radius, Color bgColor) { super(layout); cornerRadius = radius; backgroundColor = bgColor; } public RoundedPanel(int radius) { super(); cornerRadius = radius; } public RoundedPanel(int radius, Color bgColor) { super(); cornerRadius = radius; backgroundColor = bgColor; } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Dimension arcs = new Dimension(cornerRadius, cornerRadius); int width = getWidth(); int height = getHeight(); Graphics2D graphics = (Graphics2D) g; graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); //Draws the rounded panel with borders. if (backgroundColor != null) { graphics.setColor(backgroundColor); } else { graphics.setColor(getBackground()); } graphics.fillRoundRect(0, 0, width-1, height-1, arcs.width, arcs.height); //paint background graphics.setColor(getForeground()); graphics.drawRoundRect(0, 0, width-1, height-1, arcs.width, arcs.height); //paint border } } }