Graphics2D无法清除透明图像。

3
我有以下的代码片段,应该可以在第一个监视器上的透明背景上增加计数器。当图像显示0时,它会正常渲染,但之后(一旦命中1),窗口将以不透明背景重绘。
实际上,这只是个愚蠢的例子,我只是把一个真实的用例简化成了更简单的代码块。
看来关键可能在TestCanvas的paintComponent方法中。
g.setColor(new Color(0, 0, 0, 0));
g.clearRect(0, 0, getWidth(), getHeight());

根据我的理解,这两行代码应该将绘图颜色设置为完全透明,然后用该颜色清除给定区域的内容。但是,似乎在第一次重绘之后就不再生效了。
编辑:使用fillRect而不是clearRect无法解决问题,因为它只是在现有图像上绘制透明矩形,所以它永远不会被清除。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();
    }
}
4个回答

4

事实证明,在绘画之前,我需要设置正确的组合值。添加

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

将代码添加到paintComponent()方法的开头,然后使用fillRect()即可解决问题!

2
如此奇怪,该解决方案在Windows上运行正常,但在Ubuntu上却不行。:( - ferrerverck

3

尝试使用 g.fillRect(...) 代替 g.clearRect(...)。我认为我曾经遇到过类似的问题,这可能已经解决了我的问题。

我找到了适用于 BufferedImages 的原始解决方案。不确定为什么白色可能有效而黑色却无效,但可以尝试一下:

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

来自Color类的Javadoc:

alpha值为1.0或255表示颜色完全不透明,alpha值为0或0.0表示颜色完全透明。


(说明:该段文字介绍了在Java中使用Color类时,alpha值的含义。其中,alpha值是指颜色的透明度,范围从0到1或0到255不等,数值越大表示颜色越不透明,数值越小表示颜色越透明。)

1
请再尝试我的解决方案。它与您最初的问题类似,但对于清除“BufferedImage”,它对我有效。 - Nate
1
谢谢,+1 确实有效 - 不过我已经用另一种方法解决了(请看下面我的答案)。 - Michael Berry

1

我知道这有点老了,但是为什么不直接使用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);
}

这将使你得到一个完全空白的图形对象,可供绘制。

0

如果您的颜色完全透明,那么清除操作实际上会做些什么呢?

尝试将 alpha 值设置为 255,而不是 0。问题是,这将使矩形“清空”成黑色(0, 0, 0),但我不确定是否可能使用 clearRect 将其“清空”为透明。您可以尝试改用 fillRect


谢谢你的回答,不幸的是 fillRect 不起作用 - 请看编辑。 - Michael Berry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接