2012-07-02 47 views
5

我剛剛擴展了JPanel以用於我們希望看起來更「3D」的項目。這是我的老闆在組件上需要陰影和圓角的方法。這已經完成了許多在線示例中的顯示。我這樣做是這樣的:向JPanel添加一個帶圓角的背景圖片

public class RoundedPanel extends JPanel 
{ 
    protected int _strokeSize = 1; 
    protected Color _shadowColor = Color.BLACK; 
    protected boolean _shadowed = true; 
    protected boolean _highQuality = true; 
    protected Dimension _arcs = new Dimension(30, 30); 
    protected int _shadowGap = 5; 
    protected int _shadowOffset = 4; 
    protected int _shadowAlpha = 150; 

    protected Color _backgroundColor = Color.LIGHT_GRAY; 

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

    @Override 
    public void setBackground(Color c) 
    { 
     _backgroundColor = c; 
    } 

    @Override 
    protected void paintComponent(Graphics g) 
    { 
     super.paintComponent(g); 

     int width = getWidth(); 
     int height = getHeight(); 
     int shadowGap = this._shadowGap; 
     Color shadowColorA = new Color(_shadowColor.getRed(), _shadowColor.getGreen(), _shadowColor.getBlue(), _shadowAlpha); 
     Graphics2D graphics = (Graphics2D) g; 

     if(_highQuality) 
     { 
      graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     } 

     if(_shadowed) 
     { 
      graphics.setColor(shadowColorA); 
      graphics.fillRoundRect(_shadowOffset, _shadowOffset, width - _strokeSize - _shadowOffset, 
        height - _strokeSize - _shadowOffset, _arcs.width, _arcs.height); 
     } 
     else 
     { 
      _shadowGap = 1; 
     } 

     graphics.setColor(_backgroundColor); 
     graphics.fillRoundRect(0, 0, width - shadowGap, height - shadowGap, _arcs.width, _arcs.height); 
     graphics.setStroke(new BasicStroke(_strokeSize)); 
     graphics.setColor(getForeground()); 
     graphics.drawRoundRect(0, 0, width - shadowGap, height - shadowGap, _arcs.width, _arcs.height); 
     graphics.setStroke(new BasicStroke()); 
    } 
} 

我創建用下面的代碼測試框架:

public class UITest 
{ 
    private static JFrame mainFrame; 
    private static ImagePanel mainPanel; 

    public static void main(String[] args) 
    { 
     EventQueue.invokeLater(new Runnable() 
     { 
      public void run() 
      { 
       mainFrame = new JFrame(); 
       mainFrame.setVisible(true); 

       try 
       { 
        mainPanel = new ImagePanel(ImageIO.read(this.getClass().getResource("/content/diamondPlate_Light.jpg"))); 
        //mainPanel.setBounds(0, 0, 800, 600); 
       } 
       catch(IOException e) 
       { 

       } 
       mainPanel.setLayout(null); 

       RoundedPanel rPanel = new RoundedPanel(); 
       rPanel.setBounds(10, 10, 200, 200); 
       rPanel.setBackground(new Color(168, 181, 224)); 

       mainPanel.add(rPanel); 

       rPanel = new RoundedPanel(); 
       rPanel.setBounds(220, 10, 560, 200); 
       rPanel.setBackground(new Color(168, 224, 168)); 

       mainPanel.add(rPanel); 

       rPanel = new RoundedPanel(); 
       rPanel.setBounds(10, 220, 770, 300); 
       rPanel.setBackground(new Color(224, 168, 168)); 

       mainPanel.add(rPanel); 

       mainFrame.setSize(800, 600); 
       mainFrame.getContentPane().add(mainPanel); 
      } 
     }); 
    } 
} 

而且它在這個(沒有結果的背景圖像JFramecontentPane

Panels

我真正想做的是生成帶圓角的紅色,綠色和藍色面板,但由一個不同的圖像,而不是Color。我仍然需要適當的圓角,但我不確定如何做到這一點。

如果我有一個很大的紋理,我可以簡單地將它的一部分「剪」成RoundedPanel的大小和形狀嗎?我需要對此進行評估,因爲它只是在我輸入時發生的,但是如果我可以創建一個像graphics.fillRoundRect(...)中使用的幾何體之類的幾何體,然後剪切圖像,這可能會起作用。

有沒有其他的方法來做到這一點,我錯過了?我很感激你可能提供的任何反饋。謝謝。

編輯:

基於以下選擇的解決方案的想法,我已經得到了以下結果:

Panels

它需要攪打成形狀用於生產,背景圖片選擇不當,但作爲演示,以下RoundedPanel代碼使我們得到以上結果:

public class RoundedPanel extends JPanel 
{ 
    protected int strokeSize = 1; 
    protected Color _shadowColor = Color.BLACK; 
    protected boolean shadowed = true; 
    protected boolean _highQuality = true; 
    protected Dimension _arcs = new Dimension(30, 30); 
    protected int _shadowGap = 5; 
    protected int _shadowOffset = 4; 
    protected int _shadowAlpha = 150; 

    protected Color _backgroundColor = Color.LIGHT_GRAY; 
    protected BufferedImage image = null; 

    public RoundedPanel(BufferedImage img) 
    { 
     super(); 
     setOpaque(false); 

     if(img != null) 
     { 
      image = img; 
     } 
    } 

    @Override 
    public void setBackground(Color c) 
    { 
     _backgroundColor = c; 
    } 

    @Override 
    protected void paintComponent(Graphics g) 
    { 
     super.paintComponent(g); 

     int width = getWidth(); 
     int height = getHeight(); 
     int shadowGap = this._shadowGap; 
     Color shadowColorA = new Color(_shadowColor.getRed(), _shadowColor.getGreen(), _shadowColor.getBlue(), _shadowAlpha); 
     Graphics2D graphics = (Graphics2D) g; 

     if(_highQuality) 
     { 
      graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     } 

     if(shadowed) 
     { 
      graphics.setColor(shadowColorA); 
      graphics.fillRoundRect(_shadowOffset, _shadowOffset, width - strokeSize - _shadowOffset, 
        height - strokeSize - _shadowOffset, _arcs.width, _arcs.height); 
     } 
     else 
     { 
      _shadowGap = 1; 
     } 

     RoundRectangle2D.Float rr = new RoundRectangle2D.Float(0, 0, (width - shadowGap), (height - shadowGap), _arcs.width, _arcs.height); 

     Shape clipShape = graphics.getClip(); 

     if(image == null) 
     { 
      graphics.setColor(_backgroundColor); 
      graphics.fill(rr); 
     } 
     else 
     { 
      RoundRectangle2D.Float rr2 = new RoundRectangle2D.Float(0, 0, (width - strokeSize - shadowGap), (height - strokeSize - shadowGap), _arcs.width, _arcs.height); 

      graphics.setClip(rr2); 
      graphics.drawImage(this.image, 0, 0, null); 
      graphics.setClip(clipShape); 
     } 

     graphics.setColor(getForeground()); 
     graphics.setStroke(new BasicStroke(strokeSize)); 
     graphics.draw(rr); 
     graphics.setStroke(new BasicStroke()); 
    } 
} 

感謝您的幫助。

+1

[maybe](http://stackoverflow.com/questions/8416295/component-painting-outside-custom-border)或[maybe](http://stackoverflow.com/questions/9382426/how-去除拉伸標記自定義按鈕邊框) – mKorbel

+0

@mKorbel:第一個鏈接非常好。顯然,我正在尋找錯誤的術語。謝謝。 –

回答

3

試試「剪裁區域」(見g.setClip()調用):

public static void main(String[] args) { 
    JFrame f = new JFrame(); 
    f.setSize(new Dimension(600, 400)); 
    f.getContentPane().setLayout(null); 
    RoundPanel rp = new RoundPanel(); 
    rp.setBounds(100, 50, 400, 300); 
    f.getContentPane().add(rp); 
    f.setVisible(true); 
} 

static class RoundPanel extends JPanel { 
    @Override 
    protected void paintComponent(Graphics g) { 
     // Prepare a red rectangle 
     BufferedImage bi = new BufferedImage(400, 300, BufferedImage.TYPE_INT_ARGB); 
     Graphics2D gb = bi.createGraphics(); 
     gb.setPaint(Color.RED); 
     gb.fillRect(0, 0, 400, 300); 
     gb.dispose(); 

     // Set a rounded clipping region: 
     RoundRectangle2D r = new RoundRectangle2D.Float(0, 0, 400, 300, 20, 20); 
     g.setClip(r); 

     // Draw the rectangle (and see whether it has round corners) 
     g.drawImage(bi, 0, 0, null); 
    } 
} 

Graphics.setClip謹防在API文檔中提到的限制:

將當前的剪貼區域設置爲任意剪輯形狀。並非所有實現Shape接口的對象都可以用來設置剪輯。唯一保證受支持的Shape對象是通過getClip方法和Rectangle對象獲取的Shape對象。

+0

用解決方案編輯原始帖子。謝謝! –

+0

爲什麼輪不平順? – user1708134