2013-03-09 70 views
0

我正在嘗試使JPanel透明,但我無法完成它的工作。是否有可能做到這一點?如何繪製透明背景?

import java.awt.*; 
import javax.swing.*; 

public class ClearPanel extends JPanel{ 
public static void main(String[] args) { 
    ClearPanel c = new ClearPanel(); 
    c.setPreferredSize(new Dimension(200, 200)); 
    c.setOpaque(false); 

    JPanel backPanel = new JPanel(); 
    backPanel.setBackground(Color.CYAN); 

    backPanel.add(c); 

    JFrame f = new JFrame(); 
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    f.setContentPane(backPanel); 
    f.pack(); 
    f.setLocationRelativeTo(null); 
    f.setVisible(true); 
} 

@Override 
protected void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    g.fillOval(0, 0, 200, 200); 
    g.clearRect(45, 45, 50, 50); 

    Graphics2D g2 = (Graphics2D) g; 
    g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.0f)); 
    g2.fillRect(75, 75, 50, 50); 
} 
} 

橢圓應該是不透明的,但我想要透明的矩形。通過透明,我的意思是我應該能夠看到ClearPanel背後的面板。

從MadProgrammer的回答開始,是否有任何方法可以將灰色方塊繪製在區域之外,但在區域內保持透明?

@Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Rectangle fill = new Rectangle(getWidth(), getHeight()); 
     Graphics2D g2d = (Graphics2D) g.create(); 

     Rectangle hole = new Rectangle(0, 0, 100, 100); 

     Area area = new Area(fill); 
     area.subtract(new Area(hole)); 
     g2d.setColor(getBackground()); 
     g2d.fill(area); 

     g2d.setColor(Color.RED); 
     g2d.setComposite(AlphaComposite.SrcOver.derive(0.0f)); 
     g2d.fill(hole); 

     g2d.setComposite(AlphaComposite.SrcOver.derive(1.0f)); 
     g2d.setColor(Color.DARK_GRAY); 
     if(area.contains(0,0,100,200)) 
      g2d.fillRect(0, 0, 100, 200); 

     g2d.dispose();  
    } 
+0

沒有'drawRect()'滿足您的需求? – uba 2013-03-09 10:24:01

+0

@uba不,因爲我無法透過Jpanel看到,我仍然會看到矩形繪製的橢圓。 – 2013-03-09 10:25:55

+0

*「我試圖讓一片JPanel透明..」*爲什麼它提供了什麼應用程序功能?我問,因爲有可能有更好的方法來實現這一功能。 – 2013-03-09 12:38:50

回答

4

你的問題是,默認情況下,JPanel是不透明的,這意味着重繪不會在它畫什麼。

您需要將面板設置爲透明,然後接管背景的繪製。

現在,真正的技巧開始。如果您只是簡單地填充組件,然後嘗試在其頂部繪製透明部分,則只需在不透明背景上繪製透明部分...並不是很有幫助。

你需要做的不是填充你想保持透明的區域。

您可以通過使用Area形狀來完成此操作,該形狀具有能夠附加/添加和刪除形狀的巧妙技巧。

enter image description here

import java.awt.AlphaComposite; 
import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Rectangle; 
import java.awt.geom.Area; 
import java.awt.geom.Ellipse2D; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class TransparentPane { 

    public static void main(String[] args) { 
     new TransparentPane(); 
    } 

    public TransparentPane() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException ex) { 
       } catch (InstantiationException ex) { 
       } catch (IllegalAccessException ex) { 
       } catch (UnsupportedLookAndFeelException ex) { 
       } 

       BackgroundPane backgroundPane = new BackgroundPane(); 
       backgroundPane.setBackground(Color.RED); 
       backgroundPane.setLayout(new BorderLayout()); 
       backgroundPane.add(new TranslucentPane()); 

       JFrame frame = new JFrame("Test"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(backgroundPane); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class BackgroundPane extends JPanel { 

     private BufferedImage bg; 

     public BackgroundPane() { 
      try { 
       bg = ImageIO.read(new File("/path/to/your/image.jpg")); 
      } catch (IOException ex) { 
       ex.printStackTrace(); 
      } 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return bg == null ? super.getPreferredSize() : new Dimension(bg.getWidth(), bg.getHeight()); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      if (bg != null) { 
       int width = getWidth() - 1; 
       int height = getHeight() - 1; 
       int x = (width - bg.getWidth())/2; 
       int y = (height - bg.getHeight())/2; 
       g.drawImage(bg, x, y, this); 
      } 
     } 

    } 

    public class TranslucentPane extends JPanel { 

     public TranslucentPane() { 
      setOpaque(false); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Rectangle fill = new Rectangle(getWidth(), getHeight()); 
      Graphics2D g2d = (Graphics2D) g.create(); 

      int width = getWidth() - 1; 
      int height = getHeight() - 1; 
      int radius = Math.min(width, height)/2; 
      int x = (width - radius)/2; 
      int y = (height - radius)/2; 

      Ellipse2D hole = new Ellipse2D.Float(x, y, radius, radius); 

      Area area = new Area(fill); 
      area.subtract(new Area(hole)); 
      g2d.setColor(getBackground()); 
      g2d.fill(area); 

      g2d.setColor(Color.RED); 
      g2d.setComposite(AlphaComposite.SrcOver.derive(0.25f)); 
      g2d.fill(hole); 

      g2d.dispose(); 
     } 

    } 

} 

更新

嗯,這花了一點時間越長,我的預期......

enter image description here

基本上,我們需要創建的面具然後,從我們想要顯示的矩形中減去孔的形狀從我們想要顯示的矩形中減去那個結果

import java.awt.AlphaComposite; 
import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Rectangle; 
import java.awt.geom.Area; 
import java.awt.geom.Ellipse2D; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class TransparentPane { 

    public static void main(String[] args) { 
     new TransparentPane(); 
    } 

    public TransparentPane() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException ex) { 
       } catch (InstantiationException ex) { 
       } catch (IllegalAccessException ex) { 
       } catch (UnsupportedLookAndFeelException ex) { 
       } 

       BackgroundPane backgroundPane = new BackgroundPane(); 
       backgroundPane.setBackground(Color.RED); 
       backgroundPane.setLayout(new BorderLayout()); 
       backgroundPane.add(new TranslucentPane()); 

       JFrame frame = new JFrame("Test"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(backgroundPane); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class BackgroundPane extends JPanel { 

     private BufferedImage bg; 

     public BackgroundPane() { 
      try { 
       bg = ImageIO.read(new File("/Users/swhitehead/Dropbox/MegaTokyo/Evil_Small.jpg")); 
      } catch (IOException ex) { 
       ex.printStackTrace(); 
      } 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return bg == null ? super.getPreferredSize() : new Dimension(bg.getWidth(), bg.getHeight()); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      if (bg != null) { 
       int width = getWidth() - 1; 
       int height = getHeight() - 1; 
       int x = (width - bg.getWidth())/2; 
       int y = (height - bg.getHeight())/2; 
       g.drawImage(bg, x, y, this); 
      } 
     } 

    } 

    public class TranslucentPane extends JPanel { 

     public TranslucentPane() { 
      setOpaque(false); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Rectangle fill = new Rectangle(getWidth(), getHeight()); 
      Graphics2D g2d = (Graphics2D) g.create(); 

      int width = getWidth() - 1; 
      int height = getHeight() - 1; 
      int radius = Math.min(width, height)/2; 
      int x = (width - radius)/2; 
      int y = (height - radius)/2; 

      Ellipse2D hole = new Ellipse2D.Float(x, y, radius, radius); 

      Area area = new Area(fill); 
      area.subtract(new Area(hole)); 
      g2d.setColor(getBackground()); 
      g2d.fill(area); 

      g2d.setColor(Color.RED); 
      g2d.setComposite(AlphaComposite.SrcOver.derive(0.0f)); 
      g2d.fill(hole); 
      g2d.dispose(); 

      g2d = (Graphics2D) g.create(); 

      // Basically, we create an area that is subtraction of the window/rectangle 
      // from the whole. This leaves us with a rectangle (with a hole in it) 
      // that doesn't include the area where the whole is... 
      Rectangle win = new Rectangle(
          x + (radius/2), 
          y + (radius/2), radius, (radius/4)); 
      area = new Area(win); 
      area.subtract(new Area(hole)); 

      // Then we create a area that is a subtraction of the original rectangle 
      // from the one with a "hole" in it... 
      Area actual = new Area(win); 
      actual.subtract(area); 
      g2d.setColor(Color.BLUE); 
      g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f)); 
      g2d.fill(actual); 

      g2d.dispose(); 
     }   
    } 
} 
+0

感謝您的回答,我已更新我的問題,如果你也想看看。再次感謝。 – 2013-03-09 11:39:45

+0

更改AlphaComposite類型。你也可以從矩形的區域開始(重疊),從透明部分減去,填充爲不透明,然後,從相同區域開始,減去透明區域以外的區域並填充該區域... – MadProgrammer 2013-03-09 20:11:09

+0

檢查更新... – MadProgrammer 2013-03-10 07:08:12