2012-05-02 70 views
3

我有下面的代碼片段,其中應該在第一臺顯示器上的透明背景上增加一個計數器。當圖像顯示0時呈現正常,但之後(只要1被擊中)窗口重繪爲不透明背景。Graphics2D沒有清除透明圖像

在實踐中的愚蠢例子我知道,只是將一個真實的用例分解成一段簡單的代碼。

看來關鍵可能是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(); 
    } 
} 

回答

2

原來我在繪畫前必須設置正確的合成值。添加

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

paintComponent()方法開始,然後使用fillRect(),沒招!

+1

奇怪的是,該解決方案在Windows上運行,但不在Ubuntu上運行。 :( – ferrerverck

2

嘗試g.fillRect(...)代替g.clearRect(...)。我想我遇到過一次類似的問題,這可能爲我解決了這個問題。

我找到了我的原始解決方案,用於與BufferedImages一起使用的問題。不知道爲什麼顏色,而黑色也不會白可能會奏效,但不妨一試:

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

Color類的Javadoc:

的1.0或255的阿爾法值是指顏色完全不透明的 和alpha值爲0或0.0意味着顏色完全透明。

+0

不,fillRect似乎沒有清除它(請參閱編輯)。 – berry120

+0

再次嘗試我的解決方案。它與你原來的問題很相似,但它對我來說清除了'BufferedImage'。 – Nate

+0

謝謝,+1似乎確實有效 - 儘管我已經以另一種方式解決了它(請參閱下面的答案)。 – berry120

0

如果您的顏色是完全透明的,那麼結算是否真的做了什麼?

嘗試將alpha值設置爲255而不是0.問題是,這會將該矩形「清除」爲黑色(0, 0, 0),但我不確定是否可以使用clearRect將其清除爲透明。您可以嘗試使用fillRect

+0

感謝您的回答,不幸的是fillRect不起作用 - 請參閱編輯。 – berry120

0

我知道這有點舊,但爲什麼不使用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); 
} 

這應該給你一個完全空白的圖形對象來繪製。