Graphics2D not clearing transparent image

北慕城南 提交于 2019-12-13 15:15:07

问题


I have the following snippet of code which should increment a counter on a transparent background on the first monitor. When the image shows 0 it renders fine, but after that (as soon as 1 is hit) the window redraws with an opaque background.

Silly example in practice I know, just broken a real use case down to a simpler piece of code.

It seems the key might be in the paintComponent method of TestCanvas:

g.setColor(new Color(0, 0, 0, 0));
g.clearRect(0, 0, getWidth(), getHeight());

From what I can work out, those two lines should set the drawing colour to completely transparent, then clear the given area with that colour - but this doesn't seem to be holding for beyond the first repaint.

EDIT: Using fillRect instead of clearRect doesn't work because it just paints the transparent rectangle on top of the existing image, so it never gets cleared. 1 is overlayed on 0, then 2 overlayed on 1, etc.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import javax.swing.JPanel;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;

public class LyricWindow extends JWindow {

    private final TestCanvas canvas;

    public LyricWindow(Rectangle area, boolean stageView) {
        setBackground(new Color(0, 0, 0, 0));
        setArea(area);
        canvas = new TestCanvas();
        canvas.setPreferredSize(new Dimension((int) (area.getMaxX() - area.getMinX()), (int) (area.getMaxY() - area.getMinY())));
        add(canvas);
        new Thread() {

            public void run() {
                for(int i = 0; true; i++) {
                    final int ii = i;
                    SwingUtilities.invokeLater(new Runnable() {

                        @Override
                        public void run() {
                            canvas.setText(Integer.toString(ii));
                        }
                    });
                    try {
                        Thread.currentThread().sleep(200);
                    }
                    catch(InterruptedException ex) {}
                    System.out.println(ii);
                }
            }
        }.start();
    }

    public final void setArea(final Rectangle area) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                if(canvas != null) {
                    canvas.setPreferredSize(new Dimension((int) (area.getMaxX() - area.getMinX()), (int) (area.getMaxY() - area.getMinY())));
                }
                setSize((int) (area.getMaxX() - area.getMinX()), (int) (area.getMaxY() - area.getMinY()));
                setLocation((int) area.getMinX(), (int) area.getMinY());
            }
        });
    }

    public static void main(String[] args) {
        LyricWindow w = new LyricWindow(GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0].getConfigurations()[0].getBounds(), false);
        w.setVisible(true);
    }
}

class TestCanvas extends JPanel {

    private String text;

    @Override
    public void paintComponent(Graphics g) {
        g.setColor(new Color(0, 0, 0, 0));
        g.clearRect(0, 0, getWidth(), getHeight());
        g.setColor(Color.RED);
        g.drawString(text, 100, 100);
    }

    public void setText(String s) {
        text = s;
        repaint();
    }
}

回答1:


Turned out I had to set the correct composite value before painting. Adding

((Graphics2D)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC));

to the start of the paintComponent() method, then using fillRect(), did the trick!




回答2:


Try g.fillRect(...) instead of g.clearRect(...). I think I ran into a similar problem once, and this may have solved it for me.

I found my original solution to the problem for use with BufferedImages. Not sure why the color White might work while Black would not, but give it a try:

g.setBackground(new Color(255, 255, 255, 0));
g.clearRect(0, 0, width, height);

From the Color class's Javadoc:

An alpha value of 1.0 or 255 means that the color is completely opaque and an alpha value of 0 or 0.0 means that the color is completely transparent.




回答3:


If your color is completely transparent, does the clearing actually do anything?

Try setting the alpha value to 255, instead of 0. Problem is, that will "clear" the rectangle to black (0, 0, 0), but I'm not sure it's possible to "clear" it to transparent with clearRect. You might try fillRect instead.




回答4:


I know this is a bit old, however why don't you just use the JPanel's already built functionality to clear the canvas for you by calling the function in the super class?

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.setColor(new Color(0, 0, 0, 0));
    g.clearRect(0, 0, getWidth(), getHeight());
    g.setColor(Color.RED);
    g.drawString(text, 100, 100);
}

That should leave you with a completely blank graphics object to draw on.



来源:https://stackoverflow.com/questions/10406750/graphics2d-not-clearing-transparent-image

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!