在Java Graphics2D中绘制透明图像

我想在另一个上面绘制一个部分透明的图像(在物体上制作阴影)。 我目前正在使用java的Graphics2D类进行渲染,我被告知将复合设置为AlphaComposite,但这只是将它设置为完全透明。

我可以使用当前设置执行此操作吗? 我该怎么做才能解决这个问题?

这是我被告知的代码将使其部分透明:

AlphaComposite ac = java.awt.AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.5F); g.setComposite(ac); 

(我顺便使用png图像)

inheritance你的sscce(这些都是在不同的类,但我把它们放在一起以简化)(我在本地文件夹“Images”中使用一个名为“Test”的图像,你可以使用任何东西,只要它是一个png图像命名一样

 import java.awt.AlphaComposite; import java.awt.Color; import java.awt.DisplayMode; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Window; import javax.swing.ImageIcon; import com.blazingkin.atrox.ScreenManager; public class AtroxAdventrum{ public static void main(String[] args) { new AtroxAdventrum().run(); } private static DisplayMode modes[] = { //new DisplayMode(1080,720,32,0), //new DisplayMode(1080,720,24,0), //new DisplayMode(1080,720,16,0), //new DisplayMode(1440,900,32,0), //new DisplayMode(1440,900,24,0), //new DisplayMode(1440,900,16,0), }; private boolean running = true; public ScreenManager s; public void stop(){ running = false; } public void run(){ try{ init(); gameLoop(); }finally{ s.restoreScreen(); } } public void init(){ s = new ScreenManager(); DisplayMode dm = s.findFirstCompatibleMode(modes); s.setFullScreen(dm); Window w = s.getFullScreenWindow(); w.setFont(new Font("Arial", Font.PLAIN, 20)); w.setBackground(Color.black); w.setForeground(Color.white); } public void gameLoop(){ long startTime = System.currentTimeMillis(); long cumTime = startTime; while (running) { long timePassed = System.currentTimeMillis() - cumTime; cumTime += timePassed; if (limitfps){ try{ Thread.sleep(15); }catch(Exception e){} } update(timePassed); Graphics2D g = s.getGraphics(); draw(g); g.dispose(); s.update(); } } public void update(long timePassed){ } public boolean limitfps = false; public void draw(Graphics2D g){ g.clearRect(0, 0, s.getWidth(), s.getHeight()); AlphaComposite ac = java.awt.AlphaComposite.getInstance(AlphaComposite.CLEAR,0.5F); g.setComposite(ac); g.drawImage(new ImageIcon("Images/Test.png").getImage(), 30, 30, 30, 30, null); } } 

如果你运行它,你将不得不alt + tab并结束该过程(因为它没有在这部分代码中做任何事情)

您使用了错误的规则 – 请勿使用AlphaComposite.CLEAR。

AlphaComposite API说明了有关CLEAR的信息:

目的地的颜色和阿尔法都被清除(Porter-Duff清除规则)。 源和目标都不用作输入。

所以这会使图像消失。 试验其他规则。 当你创建你的SSCCE时,我创建了我的。 看看当你为另一个注释掉一个规则行时会发生什么。 例如改变这个

 // int rule = AlphaComposite.CLEAR; int rule = AlphaComposite.SRC_OVER; 

对此:

 int rule = AlphaComposite.CLEAR; // int rule = AlphaComposite.SRC_OVER; 

整个SSCCE:

 import java.awt.AlphaComposite; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Composite; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.Stroke; import java.awt.image.BufferedImage; import javax.swing.*; public class TestAlphaComposite extends JPanel { private static final int PREF_W = 400; private static final int PREF_H = PREF_W; private static final Stroke BASIC_STROKE = new BasicStroke(6f); BufferedImage backgroundImage; BufferedImage overlayImage; public TestAlphaComposite() { backgroundImage = createBackGroundImage(); overlayImage = createOverlayImage(); } private BufferedImage createBackGroundImage() { BufferedImage img = new BufferedImage(PREF_W, PREF_H, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setStroke(BASIC_STROKE); g2.setColor(Color.blue); int circleCount = 10; for (int i = 0; i < circleCount ; i++) { int x = (i * PREF_W) / (2 * circleCount); int y = x; int w = PREF_W - 2 * x; int h = w; g2.drawOval(x, y, w, h); } g2.dispose(); return img; } private BufferedImage createOverlayImage() { BufferedImage img = new BufferedImage(PREF_W, PREF_H, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setStroke(BASIC_STROKE); g2.setColor(Color.red); int circleCount = 10; for (int i = 0; i < circleCount + 1; i++) { int x1 = (i * PREF_W) / (circleCount); int y1 = 0; int x2 = PREF_W - x1; int y2 = PREF_H; float alpha = (float)i / circleCount; if (alpha > 1f) { alpha = 1f; } // int rule = AlphaComposite.CLEAR; int rule = AlphaComposite.SRC_OVER; Composite comp = AlphaComposite.getInstance(rule , alpha ); g2.setComposite(comp ); g2.drawLine(x1, y1, x2, y2); } g2.dispose(); return img; } @Override public Dimension getPreferredSize() { return new Dimension(PREF_W, PREF_H); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if (backgroundImage != null) { g.drawImage(backgroundImage, 0, 0, null); } if (overlayImage != null) { g.drawImage(overlayImage, 0, 0, null); } } private static void createAndShowGui() { JFrame frame = new JFrame("TestAlphaComposite"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new TestAlphaComposite()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGui(); } }); } } 

顺便说一句,您的SSCCE不是真正的SSCCE。 我们任何人都无法编译或运行该代码,因为它具有我们无法访问的依赖项,即“com.blazingkin.atrox.ScreenManager”。 如果您将来需要我们的帮助,您将需要编写更好的符合sscce的。