简体   繁体   English

Graphics2D没有清除透明图像

[英]Graphics2D not clearing transparent image

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. 当图像显示为0时,它呈现正常,但在此之后(一旦命中1),窗口将重绘不透明背景。

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: 似乎关键可能在TestCanvas的paintComponent方法中:

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. 编辑:使用fillRect而不是clearRect不起作用,因为它只是在现有图像的顶部绘制透明矩形,因此它永远不会被清除。 1 is overlayed on 0, then 2 overlayed on 1, etc. 1覆盖在0上,然后2覆盖在1上,等等。

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

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! paintComponent()方法的开头,然后使用fillRect() ,诀窍!

Try g.fillRect(...) instead of g.clearRect(...). 尝试g.fillRect(...)而不是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 . 我找到了与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: Color类的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. Alpha值为1.0或255表示颜色完全不透明,alpha值为0或0.0表示颜色完全透明。

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 . 尝试将alpha值设置为255而不是0.问题是,这会将矩形“清除”为黑色(0, 0, 0) ,但我不确定是否可以使用clearRect将其“清除”为透明。 You might try fillRect instead. 您可以尝试使用fillRect

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? 我知道这有点旧了,但是你为什么不通过调用超类中的函数来使用JPanel已经构建的功能来为你清除画布?

@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. 这应该让你有一个完全空白的图形对象来绘制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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