假设我有一个JPanel,其上绘制的图像是paintComponent()
的背景,此面板包含一些带图标的按钮。按钮没有自己的背景,并“继承”面板的背景。我知道如何使用AlphaComposite
创建一个半透明的按钮图标,但是如何才能获得按钮的背景图像(这是JPanel背景图像的 part 按钮是不透明的,并在面板的背景上绘制)并使其透明,而不是图标?我甚至不知道这是否可能......
以下代码只是使按钮的图标透明。
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TestPanel extends JPanel {
private final ImageIcon icon = new ImageIcon(getClass().getResource("path\\to\\image\\file"));
private BufferedImage img;
public TestPanel() {
try {
img = ImageIO.read(new File("path\\to\\background\\image"));
} catch (IOException ex) {}
ImageIcon fadedIcon = getTranslucentImageIcon(icon, 0.5f);
JButton button = new JButton(fadedIcon);
button.setRolloverIcon(icon);
button.setBorder(BorderFactory.createLineBorder(Color.BLACK));
button.setOpaque(false);
button.setContentAreaFilled(false);
button.setFocusPainted(false);
this.add(button);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img, 0, 0, null);
}
@Override
public Dimension getPreferredSize() {
if (img != null) {
return new Dimension(img.getWidth(), img.getHeight());
}
return super.getPreferredSize();
}
private BufferedImage getTranslucentImage(BufferedImage oldImg, float alpha) {
int w = oldImg.getWidth();
int h = oldImg.getHeight();
BufferedImage newImg = new BufferedImage(w, h, BufferedImage.TRANSLUCENT);
Graphics2D g2d = newImg.createGraphics();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
g2d.drawImage(oldImg, null, 0, 0);
g2d.dispose();
return newImg;
}
private ImageIcon getTranslucentImageIcon(Icon oldIcon, float alpha) {
int w = oldIcon.getIconWidth();
int h = oldIcon.getIconHeight();
BufferedImage oldImg = new BufferedImage(w, h, BufferedImage.TRANSLUCENT);
Graphics2D g2d = (Graphics2D) oldImg.getGraphics();
oldIcon.paintIcon(null, g2d, 0, 0);
BufferedImage newImg = getTranslucentImage(oldImg, alpha);
g2d.dispose();
return new ImageIcon(newImg);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
你只需要2个图像来重现它(背景图像应该更大,以使我的观点清晰)。
P.S。我还想知道我是否正在做整件事(更具体的方法是getTranslucentImage
和getTranslucentImageIcon
),或者是否有更好的方法来做到这一点。
答案 0 :(得分:3)
我会把它放在这里,因为评论不适合格式化。
至于你的“半透明”方法,它们对我来说似乎很好。我可能做的唯一改变是创建兼容的缓冲图像。这将(以及其他事项)确保颜色模型相同并使其更快地呈现...
protected BufferedImage createCompatibleImage(int width, int height, int transparency) {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gs.getDefaultConfiguration();
return gc.createCompatibleImage(width, height, transparency);
}
private BufferedImage getTranslucentImage(BufferedImage oldImg, float alpha) {
int w = oldImg.getWidth();
int h = oldImg.getHeight();
BufferedImage newImg = createCompatibleImage(w, h, Transparency.TRANSLUCENT);
Graphics2D g2d = newImg.createGraphics();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
g2d.drawImage(oldImg, null, 0, 0);
g2d.dispose();
return newImg;
}
使用扩展回答更新
为了达到你想要的效果,你需要一个干净的父组件版本。那是没有孩子的副本。然后,您需要大小并将此副本绘制到屏幕外缓冲区(如缓冲图像),然后提取所需图像的一部分(或根据您的要求绘制子图像)。
坦率地说。你正在做的事情更容易......