如何绘制透明背景? [英] How to Draw a Transparent Background?

查看:152
本文介绍了如何绘制透明背景?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使JPanel的片段透明,但是我不能完全使其正常工作.可以这样做吗?

I am trying to make a piece of a JPanel transparent, but I cannot quite get it to work. Is it possible to do this?

import java.awt.*;
import javax.swing.*;

public class ClearPanel extends JPanel{
public static void main(String[] args) {
    ClearPanel c = new ClearPanel();
    c.setPreferredSize(new Dimension(200, 200));
    c.setOpaque(false);

    JPanel backPanel = new JPanel();
    backPanel.setBackground(Color.CYAN);

    backPanel.add(c);

    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setContentPane(backPanel);
    f.pack();
    f.setLocationRelativeTo(null);
    f.setVisible(true);
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.fillOval(0, 0, 200, 200);
    g.clearRect(45, 45, 50, 50);

    Graphics2D g2 = (Graphics2D) g;
    g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.0f));
    g2.fillRect(75, 75, 50, 50);
}
}

椭圆形应该是不透明的,但是我想要的矩形是透明的.透明是指我应该能够看到ClearPanel后面的面板.

The oval should be opaque, but the rectangles I would like to be transparent. By transparent, I mean that I should be able to see the panel behind the ClearPanel.

不使用MadProgrammer的答案,有什么办法可以使灰盒在该区域之外的地方绘制,但在该区域中的地方保持透明?

Going off of MadProgrammer's answer, is there any way to make that gray box draw where it is outside of the area, but remain transparent where it is in the area?

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Rectangle fill = new Rectangle(getWidth(), getHeight());
        Graphics2D g2d = (Graphics2D) g.create();

        Rectangle hole = new Rectangle(0, 0, 100, 100);

        Area area = new Area(fill);
        area.subtract(new Area(hole));
        g2d.setColor(getBackground());
        g2d.fill(area);

        g2d.setColor(Color.RED);
        g2d.setComposite(AlphaComposite.SrcOver.derive(0.0f));
        g2d.fill(hole);

        g2d.setComposite(AlphaComposite.SrcOver.derive(1.0f));
        g2d.setColor(Color.DARK_GRAY);
        if(area.contains(0,0,100,200))
            g2d.fillRect(0, 0, 100, 200);

        g2d.dispose();      
    }

推荐答案

默认情况下,您遇到的问题是JPanel是不透明的,这意味着重新绘制不会在其下绘制任何内容.

The problem you have is, by default, JPanel is opaque, meaning that the repaint will NOT paint anything under it.

您需要将面板设置为透明,然后接管背景绘画.

You need to set the the panel to transparent and then take over the painting of the background.

现在,真正的把戏开始了.如果仅填充组件,然后尝试在其顶部绘制透明部分,则只会在不透明的背景上绘制透明部分...不是很有帮助.

Now, the real trick begins. If you simply fill the component and then try and paint transparent section over the top of it, you will simply be painting a transparent section over a opaque background...not very helpful.

您需要做的是不填充要保持透明的区域.

What you need to do is not fill the area you want to remain transparent.

您可以使用Area形状来完成此操作,该形状有一个巧妙的技巧,可以在其中添加/添加和删除形状.

You can accomplish this by using a Area shape, which has a neat trick of been able to append/add and remove shapes from it.

import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TransparentPane {

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

    public TransparentPane() {
        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) {
                }

                BackgroundPane backgroundPane = new BackgroundPane();
                backgroundPane.setBackground(Color.RED);
                backgroundPane.setLayout(new BorderLayout());
                backgroundPane.add(new TranslucentPane());

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

    public class BackgroundPane extends JPanel {

        private BufferedImage bg;

        public BackgroundPane() {
            try {
                bg = ImageIO.read(new File("/path/to/your/image.jpg"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return bg == null ? super.getPreferredSize() : new Dimension(bg.getWidth(), bg.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (bg != null) {
                int width = getWidth() - 1;
                int height = getHeight() - 1;
                int x = (width - bg.getWidth()) / 2;
                int y = (height - bg.getHeight()) / 2;
                g.drawImage(bg, x, y, this);
            }
        }

    }

    public class TranslucentPane extends JPanel {

        public TranslucentPane() {
            setOpaque(false);
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Rectangle fill = new Rectangle(getWidth(), getHeight());
            Graphics2D g2d = (Graphics2D) g.create();

            int width = getWidth() - 1;
            int height = getHeight() - 1;
            int radius = Math.min(width, height) / 2;
            int x = (width - radius) / 2;
            int y = (height - radius) / 2;

            Ellipse2D hole = new Ellipse2D.Float(x, y, radius, radius);

            Area area = new Area(fill);
            area.subtract(new Area(hole));
            g2d.setColor(getBackground());
            g2d.fill(area);

            g2d.setColor(Color.RED);
            g2d.setComposite(AlphaComposite.SrcOver.derive(0.25f));
            g2d.fill(hole);

            g2d.dispose();
        }

    }

}

更新

好吧,这花了我预期更长的时间...

Well, that took a little longer the I expected...

基本上,我们需要创建一个形状的蒙版,从要显示的矩形中减去孔,然后从要显示的矩形中减去结果

Basically, we need to create a mask of the shape that subtracts the hole from the rectangle we want to display, then subtract that result from the rectangle we want to diplay

import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TransparentPane {

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

    public TransparentPane() {
        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) {
                }

                BackgroundPane backgroundPane = new BackgroundPane();
                backgroundPane.setBackground(Color.RED);
                backgroundPane.setLayout(new BorderLayout());
                backgroundPane.add(new TranslucentPane());

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

    public class BackgroundPane extends JPanel {

        private BufferedImage bg;

        public BackgroundPane() {
            try {
                bg = ImageIO.read(new File("/Users/swhitehead/Dropbox/MegaTokyo/Evil_Small.jpg"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return bg == null ? super.getPreferredSize() : new Dimension(bg.getWidth(), bg.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (bg != null) {
                int width = getWidth() - 1;
                int height = getHeight() - 1;
                int x = (width - bg.getWidth()) / 2;
                int y = (height - bg.getHeight()) / 2;
                g.drawImage(bg, x, y, this);
            }
        }

    }

    public class TranslucentPane extends JPanel {

        public TranslucentPane() {
            setOpaque(false);
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Rectangle fill = new Rectangle(getWidth(), getHeight());
            Graphics2D g2d = (Graphics2D) g.create();

            int width = getWidth() - 1;
            int height = getHeight() - 1;
            int radius = Math.min(width, height) / 2;
            int x = (width - radius) / 2;
            int y = (height - radius) / 2;

            Ellipse2D hole = new Ellipse2D.Float(x, y, radius, radius);

            Area area = new Area(fill);
            area.subtract(new Area(hole));
            g2d.setColor(getBackground());
            g2d.fill(area);

            g2d.setColor(Color.RED);
            g2d.setComposite(AlphaComposite.SrcOver.derive(0.0f));
            g2d.fill(hole);
            g2d.dispose();

            g2d = (Graphics2D) g.create();

            // Basically, we create an area that is subtraction of the window/rectangle
            // from the whole.  This leaves us with a rectangle (with a hole in it)
            // that doesn't include the area where the whole is...
            Rectangle win = new Rectangle(
                            x + (radius / 2), 
                            y + (radius / 2), radius, (radius / 4));
            area = new Area(win);
            area.subtract(new Area(hole));

            // Then we create a area that is a subtraction of the original rectangle
            // from the one with a "hole" in it...
            Area actual = new Area(win);
            actual.subtract(area);
            g2d.setColor(Color.BLUE);
            g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
            g2d.fill(actual);

            g2d.dispose();
        }        
    }
}

这篇关于如何绘制透明背景?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆