1

JPanel の一部を透明にしようとしていますが、うまく動作しません。これを行うことは可能ですか?

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 の背後にあるパネルが見えるようにすることです。

MadProgrammerの答えから外れて、その灰色のボックスが領域の外側にある場所を描画し、領域内にある場所を透明のままにする方法はありますか?

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

1 に答える 1

5

あなたが抱えている問題は、デフォルトでJPanelは不透明です。つまり、再描画してもその下には何も描画されません。

パネルを透明に設定してから、背景の絵を引き継ぐ必要があります。

さあ、本当のトリックが始まります。コンポーネントを単純に塗りつぶしてから、その上に透明なセクションをペイントしようとすると、不透明な背景の上に透明なセクションをペイントすることになります...あまり役に立ちません。

あなたがする必要があるのは、透明にしたい領域を埋めないことです。

Areaこれは、シェイプを追加/追加および削除できる巧妙なトリックを備えたシェイプを使用して実現できます。

ここに画像の説明を入力

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

    }

}

アップデート

うーん、思ったより時間がかかりました…

ここに画像の説明を入力

基本的には、表示したい四角形から穴を差し引いた形状のマスクを作成し、表示したい四角形からその結果を差し引く必要があります。

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();
        }        
    }
}
于 2013-03-09T10:50:56.800 に答える