2012-07-02 41 views
5

Tôi vừa mới mở rộng JPanel để sử dụng trong một dự án mà chúng tôi muốn xuất hiện nhiều hơn "3D". Đó là cách của ông chủ của tôi yêu cầu bóng và góc tròn trên các thành phần. Điều đó đã được thực hiện như được hiển thị trên nhiều ví dụ trực tuyến. Tôi đã làm điều đó như thế này:Thêm hình nền vào JPanel với các góc tròn

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

tôi đang tạo ra một khung thử nghiệm với đoạn mã sau:

:

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

Và nó kết quả trong này (sans hình nền của 's contentPaneJFrame

Panels

Điều tôi thực sự muốn làm là tạo các bảng màu đỏ, xanh lục và xanh dương với các góc được làm tròn, nhưng được lấp đầy bởi một hình ảnh khác thay vì Color. Tôi vẫn muốn các góc được làm tròn đúng cách, nhưng tôi không chắc chắn về cách làm điều này.

Nếu tôi có kết cấu lớn, tôi có thể chỉ cần "cắt" một phần của nó ra ở kích thước và hình dạng của RoundedPanel không? Tôi cần phải đánh giá điều này, vì nó chỉ xảy ra với tôi khi tôi gõ, nhưng nếu tôi có thể tạo ra một mảnh hình học như những gì được sử dụng trong graphics.fillRoundRect(...) và sau đó clip hình ảnh, điều này có thể làm việc.

Có cách nào khác để thực hiện việc này mà tôi bị thiếu không? Tôi đánh giá cao bất kỳ phản hồi nào bạn có thể cung cấp. Cảm ơn.

Edit:

Dựa trên ý tưởng trong các giải pháp được lựa chọn dưới đây, tôi đã có kết quả như sau:

Panels

Nó cần phải được đánh thành hình phục vụ sản xuất và hình nền được chọn kém, nhưng làm bản trình diễn, mã RoundedPanel sau đây cho chúng tôi các kết quả ở trên:

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

Cảm ơn sự giúp đỡ.

+1

[có thể] (http://stackoverflow.com/questions/8416295/component-painting-outside-custom-border) hoặc [có thể] (http://stackoverflow.com/questions/9382426/how- to-remove-stretch-marks-on-custom-button-border) – mKorbel

+0

@mKorbel: Liên kết đầu tiên khá tốt. Tôi đã tìm kiếm trên các thuật ngữ sai, rõ ràng. Cảm ơn. –

Trả lời

3

Hãy thử "cắt khu vực" (xem g.setClip() gọi):

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

Cẩn thận với những hạn chế nêu trong doc API cho Graphics.setClip:

Thiết lập khu vực cắt hiện tại để một clip độc đoán hình dạng. Không phải tất cả các đối tượng thực hiện giao diện Hình dạng đều có thể được sử dụng để đặt clip. Các đối tượng Shape duy nhất được đảm bảo được hỗ trợ là các đối tượng Shape được lấy thông qua phương thức getClip và thông qua các đối tượng Rectangle.

+0

Đã chỉnh sửa bài đăng gốc có giải pháp. Cảm ơn! –

+0

Tại sao không phải là vòng không trơn tru? – user1708134

Các vấn đề liên quan