简体   繁体   中英

java swing partial transparency in JPanels shown as black

I am trying to create one base JPanel with "child" JPanels that have transparent rectangles in them that show the background of the base JPanel . I only seem to be able to create transparent rectangles in both my child and base JPanel . Is there a way I can tell java to only to paint the not transparent parts of my child JPanels over the base JPanel and ignore the transparent parts?

In short I would like the black rectangle in the picture to be cyan (the background color of the base JPanel ).

A picture of the JFrame :

http://i.imgur.com/eFKs2d7.png

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.beans.Transient;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;


public class Showcase extends JFrame{

    public static void main(String[] args) {
        Showcase window = new Showcase();
    }

    public Showcase() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JPanel contentPane = new JPanel();
        contentPane.setBackground(Color.CYAN);
        setContentPane(contentPane);


        final TestPane tP = new TestPane();
        contentPane.add(tP);
        tP.setBackground(Color.BLUE);

        setVisible(true);
        pack();
    }

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

    public class TestPane extends JPanel{

        @Override
        protected void paintComponent(Graphics g) {         
            super.paintComponent(g);        
            Graphics2D g2 = (Graphics2D) g;
            g2.setBackground(new Color(0, 0, 0, 0));

            g2.clearRect(0, 0, 50,50);
            g2.dispose();
        }

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

Is there a way i can tell java to only to paint the not transparent parts

First you need to make the panel non-opaque so that the parent background is painted.

Then you can play with the Area class to create the Shape that you want to paint:

public class TestPane extends JPanel
{
    public TestPane()
    {
        setOpaque( false ); // to make it transparent.
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
/*
        Graphics2D g2 = (Graphics2D) g;
        g2.setBackground(new Color(0, 0, 0, 0));

        g2.clearRect(0, 0, 50,50);
        g2.dispose();
*/
        Graphics2D g2d = (Graphics2D) g.create();

        Shape outer = new Rectangle(0, 0, getWidth(), getHeight());
        Shape inner = new Rectangle(0, 0, 50, 50);
        Area area = new Area( outer );
        area.subtract( new Area(inner) );

        g2d.setColor( getBackground() );
        g2d.fill(area);
        g2d.dispose();
    }

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

You could use setOpaque() to make the background of the JPanel transparent, but then you couldn't draw over the rectangles that you wanted to make transparent.

So another way of doing it would be to make a BufferedImage and draw the rectangles on that image and then add that BufferedImage to the JPanel .

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.beans.Transient;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;


public class Showcase extends JFrame {

    BufferedImage img;

    public static void main(String[] args) {
        Showcase window = new Showcase();
    }

    public Showcase() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JPanel contentPane = new JPanel();
        contentPane.setBackground(Color.CYAN);
        setContentPane(contentPane);


        final TestPane tP = new TestPane();
        contentPane.add(tP);

        // make new buffered image
        img = new BufferedImage(tP.getPreferredSize().width, 
                tP.getPreferredSize().height, BufferedImage.TYPE_INT_ARGB);

        setVisible(true);
        pack();
    }

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

    public class TestPane extends JPanel{

        @Override
        protected void paintComponent(Graphics g) {              
            Graphics2D g2 = (Graphics2D) g;

            Graphics2D imgG2 = img.createGraphics();

            // make img background transparent
            imgG2.setBackground(new Color(0,0,0,0));

            imgG2.setColor(Color.red);
            imgG2.fillRect(0, 0, 100, 100);

            imgG2.clearRect(0, 0, 50, 50);

            imgG2.dispose();

            // draw buffered image to jpanel
            g2.drawImage(img, 0, 0, null);

            g2.dispose();

            super.paintComponent(g);   
        }

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

The end result will look like this:

例

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM