将背景图像添加到带有圆角的JPanel

时间:2012-07-02 20:21:10

标签: java swing awt jpanel

我刚刚将JPanel扩展用于我们希望看起来更“3D”的项目。这是我的老板要求在组件上留下阴影和圆角的方式。这已经完成,如许多在线示例所示。我是这样做的:

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

结果就是这个(没有JFrame的{​​{1}}的背景图片:

Panels

我真正想做的是生成带有圆角的红色,绿色和蓝色面板,但是用不同的图像填充而不是contentPane。我仍然想要正确的圆角,但我不确定如何做到这一点。

如果我有一个大的纹理,我可以简单地“剪切”它的一部分Color的大小和形状?我需要对此进行评估,因为它只是在我输入时发生的,但是如果我可以像RoundedPanel中那样创建一个几何体,然后剪切图像,这可能会有效。

还有其他方法可以解决这个问题吗?我很感激您提供的任何反馈。感谢。

修改

根据下面所选解决方案中的想法,我得到了以下结果:

Panels

需要将其打造成生产形状并且背景图像选择不当,但作为演示,以下graphics.fillRoundRect(...)代码将我们带到上述结果:

RoundedPanel

感谢您的帮助。

1 个答案:

答案 0 :(得分: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对象。