2013-02-22 18 views
26

Aşağıdaki ekran görüntüsü, TextBubbleBorder 'un bir testini gösterir. Dikdörtgenin dışındaki bileşenlerin köşelerini tamamıyla şeffaf olacak şekilde yapmak istiyorum. & bunun altındaki herhangi bir bileşeni gösterir. Bir etiketin BG rengini Clip (yuvarlatılmış köşelerin dışındaki alanı temsil eden) Graphics2D örneğinde ayarlayarak ve clearRect() numaralı telefonu arayarak 'sınırın içine' kısıtlamak için bir yol buldum. Bu Label 1 görülebilir. ebeveyn panelde kırmızı BG (veya herhangi bir standart olmayan renk) olduğunda bu yaklaşımın olumsuz görebilirsiniz FakatYuvarlatılmış köşeler ve saydamlıklı kenarlık

Border Test

. Köşeler varsayılan panel rengine göre varsayılan (Panel 2'da görülmesi en kolay olanı).

Sonuçta bu üst kapsayıcı olmayan bir standart renk için çalışmak istiyorum, ama kısmen esinlenerek What do I need to do to replicate this component with gradient paint?

herkes bu köşeler şeffaf almak için bir yol biliyor mu?

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 0 bir pointerSize bir 'yuvarlatılmış ile sona belirterek, (& metin alanı yukarıda belirtilen nedenlerden dolayı bir karışıklık olduğu için bir JLabel kullanarak sona) Internal padding for JTextArea with background Image için tasarlanmış iken dikdörtgen 'yerine.

+0

, sadece-parçalar temin edilir sınırları hakkında harika bir şey, orada şekil hakkında ipuçları vermeyin, bu nedenle bileşen sınırına iç alanı doldurmak için için gerçekten mümkün değildir . Geçmişte yaptığım şey aldatıldı. Esasen, istediğim özel şekle sahip bir panel oluşturdum ve daha sonra, arka plan özelliklerini sağlayan bir alt gölge gibi bir arka planın içine yerleştirilmiş bir panelin içine yerleştirdim ... – MadProgrammer

+0

Eğer "boya" yı geçersiz kılarsan (evet 'paint' ve' paintComponent' değil) ve klibi sahip olmak istediğiniz şekle ayarlayın? –

+0

Teşekkürler @mKorbel, 'mre + Stroke' dayalı bazı avcılık yapacağız. –

cevap

21

N.B. Bu kodda, paintComponent() is drawing on other components kabul edilen yanıtta düzeltilen bir kırpma hatası var. Bu, 'kırpma hatası düzeltmesi' içeriyorsa, yalnızca bir çözüm olarak düşünülmelidir.


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

olarak doğru gösteren kaynak için kod bu noktayı bakınız:

BorderTest with 0px speech pointer

BorderTest with 16px speech pointer

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); 
    } 
} 
+0

teşekkürler Dude, mah iş kaydettiniz ..: D :) – Krishna

+0

Birisi ok sağa ve sola işaret için destek ekleyebilir eğer ben zarif olurdu :) –

+1

Bu [soru] (http://stackoverflow.com/questions/35190710/ paintcomponent-is-drawing-on-other-components/35191671 # 35191671) kodunuzdan ödünç alındı ​​ve bu kenarlığı kullanan bir bileşen bir kaydırma bölmesinde kullanıldığında kırpma kodunda bir sorun bulundu. Önerilen çözümümün burada da işe yarayacağını düşünürdüm. – camickr

13

bu deneyin:

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 
    } 
    }; 

benim testiyle:

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(); 

sonucudur:

Code result

+1

Bu çözümü beğendim. Belki biraz daha az güçlü, ama çok basit ve verimli! – Sharcoux

1

güzel ve basit teşekkürler @BackSlash. Bunun üzerine genişledim, bu yüzden tekrar kullanılabilir. Bu aynı zamanda kurucuda bir arka plan renginin ayarlanmasını sağlar. Ve eğlenmek için nasıl dairesel bir panel oluşturabileceğinizi gösteriyorum.

enter image description here

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 
     } 
    } 
}