Добавьте фоновое изображение в 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'scontentPane:

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

Спасибо за помощь.

5
задан Rich Hoffman 2 July 2012 в 21:57
поделиться