2012-11-13 36 views
17

Tôi có một yếu tố JPanel và tôi muốn thêm một bóng đổ vào nó, làm thế nào tôi có thể thêm một bóng mờ mờ nhạt đẹp cho phần tử? Tôi có cần phải sử dụng các thư viện bên ngoài hoặc có cái gì đó được xây dựng trong đó tôi có thể sử dụng?JPanel Drop Shadow

Ví dụ:

enter image description here

+0

Có một câu hỏi tương tự ở đây: http://stackoverflow.com/questions/3232675/how-can-i-create-a-drop-shadow-inner-glow-and- outer-glow-in-java-swing –

+0

Tôi sẽ xem xét sử dụng JavaFX nếu bạn muốn thực hiện việc này. Tôi tin rằng nó đã được xây dựng trong hỗ trợ để làm điều này loại điều, hy vọng với HW tăng tốc. – millimoose

Trả lời

21

Vì vậy, tôi nhìn vào swingx kéo dài JPanel và đã có thể đạt được kết quả tôi đang tìm kiếm với đoạn mã sau:

public class Canvas extends JXPanel{ 

    public Canvas(){ 
     DropShadowBorder shadow = new DropShadowBorder(); 
     shadow.setShadowColor(Color.BLACK); 
     shadow.setShowLeftShadow(true); 
     shadow.setShowRightShadow(true); 
     shadow.setShowBottomShadow(true); 
     shadow.setShowTopShadow(true); 
     this.setBorder(shadow); 
    } 
} 

Và kết quả:

Dropshadow

+3

Vô tình downvoted câu trả lời của bạn, đã đi AFK và bây giờ nó sẽ không cho phép tôi upvote cho đến khi câu trả lời được chỉnh sửa. Xin lỗi bạn đời, dự định để upvote. – Zar

3

Bạn có nghĩa là một cái gì đó như thế này:

enter image description here

import java.awt.BasicStroke; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.Insets; 
import java.awt.RenderingHints; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class ShadowTest { 

    private JFrame frame; 

    public ShadowTest() { 
     initComponents(); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new ShadowTest(); 
      } 
     }); 
    } 

    private void initComponents() { 
     frame = new JFrame(); 
     frame.setTitle("Example"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//app exited when frame closes 
     frame.setResizable(false); 
     frame.setLayout(new GridBagLayout()); 
     GridBagConstraints gc = new GridBagConstraints(); 
     gc.fill = GridBagConstraints.HORIZONTAL; 
     gc.insets = new Insets(10, 10, 10, 10); 
     frame.add(new RoundedPanel(), gc); 

     //pack frame (size components to preferred size) 
     frame.pack(); 
     frame.setVisible(true);//make frame visible 
    } 
} 

class RoundedPanel extends JPanel { 

    /** 
    * Stroke size. it is recommended to set it to 1 for better view 
    */ 
    protected int strokeSize = 1; 
    /** 
    * Color of shadow 
    */ 
    protected Color shadowColor = Color.black; 
    /** 
    * Sets if it drops shadow 
    */ 
    protected boolean shady = true; 
    /** 
    * Sets if it has an High Quality view 
    */ 
    protected boolean highQuality = true; 
    /** 
    * Double values for Horizontal and Vertical radius of corner arcs 
    */ 
    protected Dimension arcs = new Dimension(0, 0); 
    //protected Dimension arcs = new Dimension(20, 20);//creates curved borders and panel 
    /** 
    * Distance between shadow border and opaque panel border 
    */ 
    protected int shadowGap = 10; 
    /** 
    * The offset of shadow. 
    */ 
    protected int shadowOffset = 4; 
    /** 
    * The transparency value of shadow. (0 - 255) 
    */ 
    protected int shadowAlpha = 150; 
    int width = 300, height = 300; 

    public RoundedPanel() { 
     super(); 
     setOpaque(false); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Color shadowColorA = new Color(shadowColor.getRed(), 
       shadowColor.getGreen(), shadowColor.getBlue(), shadowAlpha); 
     Graphics2D graphics = (Graphics2D) g; 

     //Sets antialiasing if HQ. 
     if (highQuality) { 
      graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
        RenderingHints.VALUE_ANTIALIAS_ON); 
     } 

     //Draws shadow borders if any. 
     if (shady) { 
      graphics.setColor(shadowColorA); 
      graphics.fillRoundRect(
        shadowOffset,// X position 
        shadowOffset,// Y position 
        width - strokeSize - shadowOffset, // width 
        height - strokeSize - shadowOffset, // height 
        arcs.width, arcs.height);// arc Dimension 
     } else { 
      shadowGap = 1; 
     } 

     //Draws the rounded opaque panel with borders. 
     graphics.setColor(getBackground()); 
     graphics.fillRoundRect(0, 0, width - shadowGap, 
       height - shadowGap, arcs.width, arcs.height); 
     graphics.setColor(getForeground()); 
     graphics.setStroke(new BasicStroke(strokeSize)); 
     graphics.drawRoundRect(0, 0, width - shadowGap, 
       height - shadowGap, arcs.width, arcs.height); 

     //Sets strokes to default, is better. 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(width, height); 
    } 
} 

tham khảo:

+0

Tôi muốn nó phai ra ở các cạnh. –

+0

@RyanNaddy Tôi không chắc chắn tôi hiểu ... Xin vui lòng gửi một mẫu của một số loại để hiển thị toàn bộ hiệu lực dự định –

+0

Tôi cập nhật các câu hỏi chính với một ví dụ –

10

Đây là một hoàn HACK

này sẽ yêu cầu bạn phải có một bản sao của JH-Labs Filters để thực hiện mờ

Đây là một hoạt động tốn kém vì nó sử dụng một hoạt động mờ, lý do tôi sử dụng nó là sẽ đưa vào tài khoản hình dạng của các thành phần nó là shadowing.

enter image description here

Vấn đề chính bạn phải là biên giới không phải là bản thân họ, trong suốt, không có cách nào để thực sự có một thành phần đục và một biên giới trong suốt. Hench hack

public class TestDropShadowBorder { 

    public static void main(String[] args) { 
     new TestDropShadowBorder(); 
    } 

    public TestDropShadowBorder() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException ex) { 
       } catch (InstantiationException ex) { 
       } catch (IllegalAccessException ex) { 
       } catch (UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Test"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     public TestPane() { 
      setBackground(Color.RED); 
      setBorder(new EmptyBorder(20, 20, 20, 20)); 

      setLayout(new BorderLayout()); 
      JPanel drop = new JPanel(); 
      drop.setOpaque(false); 
      DropShadowBorder border = new DropShadowBorder(); 
      border.setFillContentArea(true); 
      drop.setBorder(new CompoundBorder(border, new LineBorder(Color.BLACK))); 

      add(drop); 

     } 
    } 

    public static class DropShadowBorder implements Border { 

     protected static final int SHADOW_SIZE = 4; 
     protected static final Map<Component, DropShadowBorder.CachedBorder> BORDER_CACHE = new WeakHashMap<Component, CachedBorder>(5); 
     private boolean fillContentArea; 
     private int shadowSize; 
     private float shadowOpacity; 
     private Color shadowColor; 

     public DropShadowBorder() { 

      this(SHADOW_SIZE, Color.BLACK, 0.5f, true); 

     } 

     public DropShadowBorder(boolean paintContentArea) { 

      this(SHADOW_SIZE, Color.BLACK, 0.5f, paintContentArea); 

     } 

     public DropShadowBorder(int shadowSize) { 

      this(shadowSize, Color.BLACK, 0.5f, true); 

     } 

     public DropShadowBorder(Color shadowColor) { 

      this(SHADOW_SIZE, shadowColor, 0.5f, true); 

     } 

     public DropShadowBorder(int shadowSize, Color showColor) { 

      this(shadowSize, showColor, 0.5f, true); 

     } 

     public DropShadowBorder(int shadowSize, float opacity) { 

      this(shadowSize, Color.BLACK, opacity, true); 

     } 

     public DropShadowBorder(Color shadowColor, float opacity) { 

      this(SHADOW_SIZE, shadowColor, opacity, true); 

     } 

     public DropShadowBorder(int shadowSize, Color shadowColor, float opacity) { 

      this(shadowSize, shadowColor, opacity, true); 

     } 

     public DropShadowBorder(int shadowSize, boolean paintContentArea) { 

      this(shadowSize, Color.BLACK, 0.5f, paintContentArea); 

     } 

     public DropShadowBorder(Color shadowColor, boolean paintContentArea) { 

      this(SHADOW_SIZE, shadowColor, 0.5f, paintContentArea); 

     } 

     public DropShadowBorder(int shadowSize, Color showColor, boolean paintContentArea) { 

      this(shadowSize, showColor, 0.5f, paintContentArea); 

     } 

     public DropShadowBorder(int shadowSize, float opacity, boolean paintContentArea) { 

      this(shadowSize, Color.BLACK, opacity, paintContentArea); 

     } 

     public DropShadowBorder(Color shadowColor, float opacity, boolean paintContentArea) { 

      this(SHADOW_SIZE, shadowColor, opacity, paintContentArea); 

     } 

     public DropShadowBorder(int shadowSize, Color showColor, float opacity, boolean paintContentArea) { 

      setShadowSize(shadowSize); 
      setShadowColor(showColor); 
      setShadowOpacity(opacity); 
      setFillContentArea(paintContentArea); 

     } 

     public void setShadowColor(Color shadowColor) { 
      this.shadowColor = shadowColor; 
     } 

     public void setShadowOpacity(float shadowOpacity) { 
      this.shadowOpacity = shadowOpacity; 
     } 

     public Color getShadowColor() { 
      return shadowColor; 
     } 

     public float getShadowOpacity() { 
      return shadowOpacity; 
     } 

     public void setShadowSize(int size) { 

      shadowSize = size; 

     } 

     public int getShadowSize() { 

      return shadowSize; 

     } 

     public static GraphicsConfiguration getGraphicsConfiguration() { 

      return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); 

     } 

     public static BufferedImage createCompatibleImage(int width, int height) { 

      return createCompatibleImage(width, height, Transparency.TRANSLUCENT); 

     } 

     public static BufferedImage createCompatibleImage(int width, int height, int transparency) { 

      BufferedImage image = getGraphicsConfiguration().createCompatibleImage(width, height, transparency); 
      image.coerceData(true); 
      return image; 

     } 

     public static BufferedImage generateShadow(BufferedImage imgSource, int size, Color color, float alpha) { 

      int imgWidth = imgSource.getWidth() + (size * 2); 
      int imgHeight = imgSource.getHeight() + (size * 2); 

      BufferedImage imgMask = createCompatibleImage(imgWidth, imgHeight); 
      Graphics2D g2 = imgMask.createGraphics(); 
      g2.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); 
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
      g2.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); 
      g2.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); 
      g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); 
      g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); 
      g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 
      g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); 

      int x = Math.round((imgWidth - imgSource.getWidth())/2f); 
      int y = Math.round((imgHeight - imgSource.getHeight())/2f); 
      g2.drawImage(imgSource, x, y, null); 
      g2.dispose(); 

      // ---- Blur here --- 

      BufferedImage imgGlow = generateBlur(imgMask, size, color, alpha); 
// 
//  BufferedImage imgGlow = ImageUtilities.createCompatibleImage(imgWidth, imgHeight); 
//  g2 = imgGlow.createGraphics(); 
// 
//  g2.drawImage(imgMask, 0, 0, null); 
//  g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, alpha)); 
//  g2.setColor(color); 
// 
//  g2.fillRect(x, y, imgSource.getWidth(), imgSource.getHeight()); 
//  g2.dispose(); 
// 
//  imgGlow = filter.filter(imgGlow, null); 

      // ---- Blur here ---- 

//  imgGlow = ImageUtilities.applyMask(imgGlow, imgMask, AlphaComposite.DST_OUT); 

      return imgGlow; 

     } 

     public static BufferedImage generateBlur(BufferedImage imgSource, int size, Color color, float alpha) { 

      GaussianFilter filter = new GaussianFilter(size); 

      int imgWidth = imgSource.getWidth(); 
      int imgHeight = imgSource.getHeight(); 

      BufferedImage imgBlur = createCompatibleImage(imgWidth, imgHeight); 
      Graphics2D g2d = imgBlur.createGraphics(); 
      g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); 
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
      g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); 
      g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); 
      g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); 
      g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); 
      g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 
      g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); 

      g2d.drawImage(imgSource, 0, 0, null); 
      g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, alpha)); 
      g2d.setColor(color); 

      g2d.fillRect(0, 0, imgSource.getWidth(), imgSource.getHeight()); 
      g2d.dispose(); 

      imgBlur = filter.filter(imgBlur, null); 

      return imgBlur; 

     } 

     public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { 

      /* 
      * Because of the amount of time it can take to render the drop shadow, 
      * we cache the results in a static cache, based on the component 
      * and the components size. 
      * 
      * This allows the shadows to repainted quickly so long as the component 
      * hasn't changed in size. 
      */ 

      BufferedImage dropShadow = null; 

      DropShadowBorder.CachedBorder cached = BORDER_CACHE.get(c); 
      if (cached != null) { 

       dropShadow = cached.getImage(c); 

      } 

      if (dropShadow == null) { 

       int shadowSize = getShadowSize(); 
       float opacity = getShadowOpacity(); 
       Color color = getShadowColor(); 

       // Create a blank canvas, from which the actually border can be generated 
       // from... 
       // The ahadow routine can actually generate a non-rectangular border, but 
       // because we don't have a suitable template to run from, we need to 
       // set this up our selves... 
       // It would be nice to be able to user the component itself, but this will 
       // have to 
       BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 
       Graphics2D g2d = img.createGraphics(); 
       g2d.fillRect(0, 0, width - (shadowSize * 2), height - (shadowSize * 2)); 
       g2d.dispose(); 

       // Generate the shadow 
       BufferedImage shadow = generateShadow(img, shadowSize, getShadowColor(), getShadowOpacity()); 

       // We need to produce a clipping result, cause the border is painted ontop 
       // of the base component... 
       BufferedImage clipedShadow = createCompatibleImage(width, height, Transparency.TRANSLUCENT); 
       g2d = clipedShadow.createGraphics(); 
       Shape clip = g2d.getClip(); 

       // First we create a "area" filling the avaliable space... 
       Area area = new Area(new Rectangle(width, height)); 
       // Then we subtract the space left over for the component 
       area.subtract(new Area(new Rectangle(width - (shadowSize * 2), height - (shadowSize * 2)))); 
       // And then apply the clip 
       g2d.setClip(area); 
       // Then draw the shadow image 
//  g2d.drawImage(shadow, -(shadowSize/2), -(shadowSize/2), c); 
       g2d.drawImage(shadow, 0, 0, c); 
       g2d.setClip(clip); 

      if (!c.isOpaque() && isFillContentArea()) { 

       area = new Area(new Rectangle(width - (shadowSize * 2), height - (shadowSize * 2))); 
       g2d.setColor(c.getBackground()); 
       g2d.fill(area); 

      } 

//   g2d.setColor(Color.RED); 
//   g2d.drawRect(x, y, width - 1, height - 1); 
// 
//   g2d.setColor(Color.GREEN); 
//   g2d.drawRect(x, y, width - (shadowSize * 2), height - (shadowSize * 2)); 

       g2d.dispose(); 

       dropShadow = clipedShadow; 
       BORDER_CACHE.put(c, new CachedBorder(dropShadow, c.getSize())); 

      } 

      g.drawImage(dropShadow, x, y, c); 

//  if (!c.isOpaque() && isFillContentArea()) { 
// 
//   Graphics2D g2d = (Graphics2D) g; 
//    
//   Area area = new Area(new Rectangle(width - (shadowSize * 2), height - (shadowSize * 2))); 
//   g2d.setColor(c.getBackground()); 
//   g2d.fill(area); 
// 
//  } 

//  g.setColor(Color.MAGENTA); 
//  g.drawRect(x + 1, y + 1, width - (shadowSize * 2) - 1, height - (shadowSize * 2) - 1); 

     } 

     public Insets getBorderInsets(Component cmpnt) { 
      return new Insets(0, 0, getShadowSize() * 2, getShadowSize() * 2); 
     } 

     public boolean isBorderOpaque() { 
      return false; 
     } 

     /** 
     * Returns if the content area should be painted by this border when the 
     * parent component is opaque... 
     * 
     * The problem is, the paintComponent method will paint the WHOLE component 
     * background, including the border area. This is a reasonable assumption to 
     * make, but it makes the shadow border really show up when the parent 
     * component is a different color. 
     * 
     * This allows the border to take control of that fact. 
     * 
     * When using it, you will need to try and make this the first border to get 
     * painted though :P 
     * 
     * @return 
     */ 
     public boolean isFillContentArea() { 
      return fillContentArea; 
     } 

     public void setFillContentArea(boolean fill) { 

      fillContentArea = fill; 

     } 

     protected class CachedBorder { 

      private BufferedImage image; 
      private Dimension size; 

      public CachedBorder(BufferedImage border, Dimension size) { 

       this.image = border; 
       this.size = size; 

      } 

      public BufferedImage getImage(Component comp) { 

       BufferedImage dropShadow = null; 

       if (comp.getSize().equals(size)) { 

        dropShadow = image; 

       } 

       return dropShadow; 

      } 
     } 
    } 
} 

CẬP NHẬT với thêm Ví dụ

Biên giới bóng thả có những hạn chế, nó không thể đi vào xem xét hình dạng của các thành phần, như thời gian biên giới được vẽ, thành phần đã không bắt đầu, vì vậy chúng tôi không có điểm tham chiếu.

enter image description hereenter image description here

Để có thể tạo ra một hiệu ứng bóng đổ mà đưa vào xem xét hình dạng của các thành phần, chúng ta cần tạo một thành phần tùy chỉnh và tiêm biên giới của chúng tôi trực tiếp vào quá trình sơn.

public class TestDropShadowBorder { 

    public static void main(String[] args) { 
     new TestDropShadowBorder(); 
    } 

    public TestDropShadowBorder() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException ex) { 
       } catch (InstantiationException ex) { 
       } catch (IllegalAccessException ex) { 
       } catch (UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Test"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     public TestPane() { 
      setBackground(Color.RED); 
      setBorder(new EmptyBorder(20, 20, 20, 20)); 
      setLayout(new BorderLayout()); 
      add(new RoundedPane()); 
     } 
    } 

    public class RoundedPane extends JPanel { 

     private int shadowSize = 5; 

     public RoundedPane() { 
      // This is very important, as part of the panel is going to be transparent 
      setOpaque(false); 
     } 

     @Override 
     public Insets getInsets() { 
      return new Insets(0, 0, 10, 10); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      int width = getWidth() - 1; 
      int height = getHeight() - 1; 

      Graphics2D g2d = (Graphics2D) g.create(); 
      applyQualityProperties(g2d); 
      Insets insets = getInsets(); 
      Rectangle bounds = getBounds(); 
      bounds.x = insets.left; 
      bounds.y = insets.top; 
      bounds.width = width - (insets.left + insets.right); 
      bounds.height = height - (insets.top + insets.bottom); 

      RoundRectangle2D shape = new RoundRectangle2D.Float(bounds.x, bounds.y, bounds.width, bounds.height, 20, 20); 

      /** 
      * * THIS SHOULD BE CAHCED AND ONLY UPDATED WHEN THE SIZE OF THE 
      * COMPONENT CHANGES ** 
      */ 
      BufferedImage img = createCompatibleImage(bounds.width, bounds.height); 
      Graphics2D tg2d = img.createGraphics(); 
      applyQualityProperties(g2d); 
      tg2d.setColor(Color.BLACK); 
      tg2d.translate(-bounds.x, -bounds.y); 
      tg2d.fill(shape); 
      tg2d.dispose(); 
      BufferedImage shadow = generateShadow(img, shadowSize, Color.BLACK, 0.5f); 

      g2d.drawImage(shadow, shadowSize, shadowSize, this); 

      g2d.setColor(getBackground()); 
      g2d.fill(shape); 

      /** 
      * THIS ONE OF THE ONLY OCCASIONS THAT I WOULDN'T CALL 
      * super.paintComponent * 
      */ 
      getUI().paint(g2d, this); 

      g2d.setColor(Color.GRAY); 
      g2d.draw(shape); 
      g2d.dispose(); 
     } 
    } 

    public static GraphicsConfiguration getGraphicsConfiguration() { 

     return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); 

    } 

    public static BufferedImage createCompatibleImage(int width, int height) { 

     return createCompatibleImage(width, height, Transparency.TRANSLUCENT); 

    } 

    public static void applyQualityProperties(Graphics2D g2) { 
     g2.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     g2.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); 
     g2.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); 
     g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); 
     g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); 
     g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 
     g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); 
    } 

    public static BufferedImage createCompatibleImage(int width, int height, int transparency) { 

     BufferedImage image = getGraphicsConfiguration().createCompatibleImage(width, height, transparency); 
     image.coerceData(true); 
     return image; 

    } 

    public static BufferedImage generateShadow(BufferedImage imgSource, int size, Color color, float alpha) { 

     int imgWidth = imgSource.getWidth() + (size * 2); 
     int imgHeight = imgSource.getHeight() + (size * 2); 

     BufferedImage imgMask = createCompatibleImage(imgWidth, imgHeight); 
     Graphics2D g2 = imgMask.createGraphics(); 
     applyQualityProperties(g2); 

     int x = Math.round((imgWidth - imgSource.getWidth())/2f); 
     int y = Math.round((imgHeight - imgSource.getHeight())/2f); 
//   g2.drawImage(imgSource, x, y, null); 
     g2.drawImage(imgSource, 0, 0, null); 
     g2.dispose(); 

     // ---- Blur here --- 

     BufferedImage imgShadow = generateBlur(imgMask, size, color, alpha); 

     return imgShadow; 

    } 

    public static BufferedImage generateBlur(BufferedImage imgSource, int size, Color color, float alpha) { 

     GaussianFilter filter = new GaussianFilter(size); 

     int imgWidth = imgSource.getWidth(); 
     int imgHeight = imgSource.getHeight(); 

     BufferedImage imgBlur = createCompatibleImage(imgWidth, imgHeight); 
     Graphics2D g2d = imgBlur.createGraphics(); 
     applyQualityProperties(g2d); 

     g2d.drawImage(imgSource, 0, 0, null); 
     g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, alpha)); 
     g2d.setColor(color); 

     g2d.fillRect(0, 0, imgSource.getWidth(), imgSource.getHeight()); 
     g2d.dispose(); 

     imgBlur = filter.filter(imgBlur, null); 

     return imgBlur; 

    } 
} 
+0

Tôi tự hỏi nếu đây là những gì OP muốn, câu trả lời ban đầu của tôi là tương tự ngoại trừ đường viền tròn (thay đổi bằng cách đặt kích thước vòng cung thành 0). Có vẻ như đôi mắt của tôi không lừa dối tôi, đường viền được hiển thị lớn ở phần cuối của góc (không có góc cung hoặc góc) và đường viền mỏng hơn xung quanh phần còn lại của hình ảnh cũng không có góc hoặc vòng cung nhô ra khỏi góc hình ảnh? Hay đó là sự mờ nhạt của OP sau? 1 mặc dù đoạn trích tuyệt vời :) –

+0

Có đường viền dòng "đen" xung quanh ngăn gốc. Bóng tối bắt đầu được tạo ra bằng cách chụp nhanh thành phần và làm mờ kết quả để tạo ra một bóng đơn giản. Bóng tối hiện tại được neo về phía đông nam, nhưng nó sẽ không mất nhiều thời gian để di chuyển nó;) – MadProgrammer

+0

@DavidKroukamp Thêm ví dụ bổ sung: P – MadProgrammer

3

Bóng thả đơn giản bạn có thể làm việc. Bạn có thể thấy được triển khai trên các JPanels này.

public class DropShadowPanel extends JPanel { 

    private static final long serialVersionUID = 1L; 

    public int pixels; 

    public DropShadowPanel(int pix) { 
     this.pixels = pix; 
     Border border = BorderFactory.createEmptyBorder(pixels, pixels, pixels, pixels); 
     this.setBorder(BorderFactory.createCompoundBorder(this.getBorder(), border)); 
     this.setLayout(new BorderLayout()); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     int shade = 0; 
     int topOpacity = 80; 
     for (int i = 0; i < pixels; i++) { 
      g.setColor(new Color(shade, shade, shade, ((topOpacity/pixels) * i))); 
      g.drawRect(i, i, this.getWidth() - ((i * 2) + 1), this.getHeight() - ((i * 2) + 1)); 
     } 
    } 
} 
+0

Điều này thật tuyệt đẹp. +1. – m4heshd