简体   繁体   中英

JPanel on JWindow is not transparent if `set setOpaque(false);` - why?

How to make JPanel to be transparent in this example? The gradient background is not visible:

package test;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JWindow;

public class PaintJPanelOnJWindow extends JWindow {

    public PaintJPanelOnJWindow() {

        JPanel panel = new JPanel();

        panel.setPreferredSize(new Dimension(350, 120));
        panel.setMinimumSize(new Dimension(350, 120));
        panel.setMaximumSize(new Dimension(350, 120));

        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        panel.setOpaque(false);

        JLabel someText = new JLabel("I'm not transparent and my JPanel too :(");
        someText.setOpaque(false);
        panel.add(someText);
        add(panel);

        pack();
        setLocationRelativeTo(null);
        setVisible(true);
    }

    @Override
    public void paint(Graphics g) {

        Graphics2D g2d = (Graphics2D) g.create();
        try {
            int w = getWidth(), h = getHeight();
            g2d.setPaint(new GradientPaint(0, 0, Color.RED, 0, h, Color.WHITE));
            g2d.fillRect(0, 0, w, h);
        } finally {
            g2d.dispose();
        }
        super.paint(g);
    }
}

From JavaDocs :

create() : Creates a new Graphics object that is a copy of this Graphics object.

Which means that the Graphics object g2d is not referring to the JWindow Graphics object, it is referring to a copy of the JWindow Graphics object.

You need to change

Graphics2D g2d = (Graphics2D) g.create(); //creates a copy, wrong object

To

Graphics2D g2d = (Graphics2D) g;          //refers to the right Graphics object

UPDATE

However, this is not the right way to do it. You should override JPanel 's paintComponent method instead of breaking the window's paint process. First, remove the paint() method override from your class. Then, initialize the JPanel as follows:

JPanel panel = new JPanel() {

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        int w = getWidth(), h = getHeight();
        g2d.setPaint(new GradientPaint(0, 0, Color.RED, 0, h, Color.WHITE));
        g2d.fillRect(0, 0, w, h);
    }
};

The immediate problem is that

super.paint(g);

is being called after the custom painting code in the paint method which will cause any previous painting to be lost. Calling panel.setOpaque(false) has no effect what is done in the paint method. Calling setOpaque for any of the components in the question is unnecessary - by default the backgrounds are displayed when custom painting is correctly implemented.

This should be done by overriding the paintComponent method. This means creating a new JPanel and placing the custom painting functionality there rather than in a top level container such as a JWindow .

Example:

在此处输入图片说明

public class PaintJPanelApp {


    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame frame = new JFrame("Gradient App");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setUndecorated(true);
                frame.setLocationRelativeTo(null);

                JLabel someText = new JLabel("I AM transparent and my JPanel too :)");
                GradientPanel gradientPanel = new GradientPanel();
                gradientPanel.add(someText);
                frame.add(gradientPanel);

                frame.pack();
                frame.setVisible(true);
            }
        });
    }

    static class GradientPanel extends JPanel {


        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            int w = getWidth(); 
            int h = getHeight();
            Graphics2D g2d = (Graphics2D) g;
            g2d.setPaint(new GradientPaint(0, 0, Color.RED, 0, h, Color.WHITE));
            g2d.fillRect(0, 0, w, h);
        }
    }
}

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