将颜色应用于JButton图像的透明区域 – 但不是其容器的透明区域

我有一个圆形JButton使用圆形PNG图像和透明区域构建。

我想用给定的颜色填充JButton图像的透明区域 – 但不是包含JButton的JPanel的不透明背景颜色。 我想用Java编程,而不是从图形包中提供预先着色的图像。

我已经得到了下面的代码,它只是允许不透明面板的橙色背景为透明区域着色。 但是,我无法弄清楚如何将面板背景保持为橙色,但用蓝色(或其他颜色进行翻转和按下效果)填充图像透明度。

import java.awt.Color; import java.awt.Cursor; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.net.URL; import javax.imageio.ImageIO; import javax.swing.DefaultButtonModel; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; public class App extends JFrame implements ActionListener { public App() { super(); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setContentPane(makeContentPane()); } private final JPanel makeContentPane() { JPanel contentPane = new JPanel(); BufferedImage bi = null; try { bi = ImageIO.read(new URL("http://sofzh.miximages.com/java/1384148625_twitter_circle_gray.png")); } catch (IOException e) { e.printStackTrace(); } ImageIcon icon = new ImageIcon(bi); MyButton myButton = new MyButton(icon); myButton.addActionListener(this); contentPane.add(myButton); contentPane.setBackground(Color.ORANGE); contentPane.setOpaque(true); return contentPane; } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { App app = new App(); app.pack(); app.setVisible(true); } }); } class MyButton extends JButton { public MyButton(ImageIcon icon) { super(icon); setMargin(new Insets(0, 0, 0, 0)); setFocusable(false); setContentAreaFilled(false); setBorderPainted(false); setModel(new DefaultButtonModel()); setCursor(new Cursor(Cursor.HAND_CURSOR)); } } @Override public void actionPerformed(ActionEvent arg0) { System.out.println("You clicked me"); } } 

我猜我可能需要将Graphics2D转换应用到我的透明图像来创建一组三个新图像(对于我的JButton的正常,翻转和按下状态)。 这是正确的前进方式,如果是这样,你能为我提供一个我缺少的代码示例吗?

谢谢

尝试覆盖自定义JButton paintComponent()

这是我尝试过的

 class MyButton extends JButton { public MyButton(ImageIcon icon) { super(icon); setMargin(new Insets(0, 0, 0, 0)); setFocusable(false); setContentAreaFilled(false); setBorderPainted(false); setModel(new DefaultButtonModel()); setCursor(new Cursor(Cursor.HAND_CURSOR)); } public void paintComponent(Graphics g) { g.setColor(Color.green); g.fillOval(0, 0, this.getWidth(), this.getHeight()); super.paintComponent(g); } } 

这是结果:

在此处输入图像描述

编辑:

要使其根据鼠标移动而改变颜色,您需要将一个MouseListener添加到JButton并向该类添加Color属性,当触​​发MouseEvent时,您需要更改颜色。 另外不要忘记在paintComponent()中将图形设置为该颜色

 class MyButton extends JButton { Color color = Color.GREEN; public MyButton(ImageIcon icon) { super(icon); setMargin(new Insets(0, 0, 0, 0)); setFocusable(false); setContentAreaFilled(false); setBorderPainted(false); setModel(new DefaultButtonModel()); setCursor(new Cursor(Cursor.HAND_CURSOR)); this.addMouseListener(new MouseListener() { @Override public void mouseClicked(MouseEvent e) { } @Override public void mousePressed(MouseEvent e) { color=Color.RED; } @Override public void mouseReleased(MouseEvent e) { color=Color.BLUE; } @Override public void mouseEntered(MouseEvent e) { color=Color.BLUE; } @Override public void mouseExited(MouseEvent e) { color=Color.GREEN; } }); } @Override public void paintComponent(Graphics g) { g.setColor(color); g.fillOval(0, 0, this.getWidth(), this.getHeight()); super.paintComponent(g); } } 

好吧,这只是你要求的,但它展示了一种方法,通过它可以生成一个与图像形状相匹配的形状,基于它的alpha,通过AlphaComposite的魔力……

所以,基本上,我们将把左边的原始图像转换成右边的图像……

原版的 蒙面

  • 首先,我们加载原始图像
  • 接下来,我们创建一个我们想要实现的形状的面具(在这种情况下为圆形)
  • 接下来,我们将两个图像一起屏蔽,以便将原始图像裁剪到蒙版中(第二个)
  • 然后我们创建一个新的蒙版,它填充了我们想要用作轮廓的颜色
  • 然后我们用“轮廓”图像掩盖第一个蒙版图像,这基本上充当了一个cookies切割器,用“块”图像切割第一个蒙版图像的形状。
  • 我们采用这种“轮廓”形状,然后稍微扩大
  • 最后,我们将它们结合起来。

这个例子生成了两个图像,一个“普通”和一个“翻转”,很容易应用于JButton ,例如……

正常…

正常

滚下…

滚下

现在,如果由于某种原因,你想知道按钮何时被“翻转”,你可以简单地将一个ChangeListener添加到ButtonModel ,例如……

 JButton btn = new JButton(new ImageIcon(normal)); btn.setRolloverIcon(new ImageIcon(rollOver)); btn.setRolloverEnabled(true); btn.getModel().addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { ButtonModel model = (ButtonModel) e.getSource(); System.out.println("Change: " + model.isRollover()); } }); 

可运行的例子……

 import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridBagLayout; import java.awt.Image; import java.awt.RenderingHints; import java.awt.Transparency; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; 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.ButtonModel; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; public class JavaApplication24 { public static void main(String[] args) { new JavaApplication24(); } public JavaApplication24() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } catch (IOException ex) { Logger.getLogger(JavaApplication24.class.getName()).log(Level.SEVERE, null, ex); } } }); } public class TestPane extends JPanel { public TestPane() throws IOException { setLayout(new GridBagLayout()); BufferedImage source = ImageIO.read(...)); // This the shape we want the source to be clipped to int size = Math.min(source.getWidth(), source.getHeight()); BufferedImage mask = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); Graphics2D maskg = mask.createGraphics(); applyQualityRenderingHints(maskg); maskg.setColor(Color.WHITE); maskg.fillOval((source.getWidth() - size) / 2, (source.getHeight() - size) / 2, size, size); maskg.dispose(); // This will mask the source to the shape we've defined BufferedImage masked = applyMask(source, mask, AlphaComposite.DST_ATOP); BufferedImage normal = makeOutline(masked, Color.BLACK); BufferedImage rollOver = makeOutline(masked, Color.RED); JButton btn = new JButton(new ImageIcon(normal)); btn.setRolloverIcon(new ImageIcon(rollOver)); btn.setRolloverEnabled(true); btn.getModel().addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { ButtonModel model = (ButtonModel) e.getSource(); System.out.println("Change: " + model.isRollover()); } }); add(btn); } protected BufferedImage makeOutline(BufferedImage original, Color color) { // This generates a image which is completely filled with the provided color BufferedImage outline = new BufferedImage(original.getWidth(), original.getHeight(), BufferedImage.TYPE_INT_ARGB); Graphics2D outlineg = outline.createGraphics(); applyQualityRenderingHints(outlineg); outlineg.setColor(color); outlineg.fillRect(0, 0, outline.getWidth(), outline.getHeight()); outlineg.dispose(); // This applies a AlphaComposite to mask the outline with the shape // of the original image outline = applyMask(original, outline, AlphaComposite.SRC_ATOP); // Now we make it slightly larger... double scale = 1.05; outline = getScaledInstanceToFit(outline, scale); // And we combine the images outlineg = outline.createGraphics(); int x = (outline.getWidth() - original.getWidth()) / 2; int y = (outline.getHeight() - original.getHeight()) / 2; outlineg.drawImage(original, x, y, this); outlineg.dispose(); return outline; } public BufferedImage applyMask(BufferedImage sourceImage, BufferedImage maskImage) { return applyMask(sourceImage, maskImage, AlphaComposite.DST_IN); } public BufferedImage applyMask(BufferedImage sourceImage, BufferedImage maskImage, int method) { BufferedImage maskedImage = null; if (sourceImage != null) { int width = maskImage.getWidth(null); int height = maskImage.getHeight(null); maskedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D mg = maskedImage.createGraphics(); applyQualityRenderingHints(mg); int x = (width - sourceImage.getWidth(null)) / 2; int y = (height - sourceImage.getHeight(null)) / 2; mg.drawImage(sourceImage, x, y, null); mg.setComposite(AlphaComposite.getInstance(method)); mg.drawImage(maskImage, 0, 0, null); mg.dispose(); } return maskedImage; } public void applyQualityRenderingHints(Graphics2D g2d) { g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); // g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); } public BufferedImage getScaledInstanceToFit(BufferedImage img, double scale) { int width = (int)(img.getWidth() * scale); int height = (int)(img.getHeight()* scale); return getScaledInstanceToFit(img, new Dimension(width, height)); } public BufferedImage getScaledInstanceToFit(BufferedImage img, Dimension size) { double scaleFactor = getScaleFactorToFit(new Dimension(img.getWidth(), img.getHeight()), size); return getScaledInstance(img, scaleFactor); } public double getScaleFactorToFit(Dimension original, Dimension toFit) { double dScale = 1d; if (original != null && toFit != null) { double dScaleWidth = getScaleFactor(original.width, toFit.width); double dScaleHeight = getScaleFactor(original.height, toFit.height); dScale = Math.min(dScaleHeight, dScaleWidth); } return dScale; } public double getScaleFactor(int iMasterSize, int iTargetSize) { return (double) iTargetSize / (double) iMasterSize; } public BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor) { return getScaledInstance(img, dScaleFactor, RenderingHints.VALUE_INTERPOLATION_BILINEAR, true); } protected BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor, Object hint, boolean bHighQuality) { BufferedImage imgScale = img; int iImageWidth = (int) Math.round(img.getWidth() * dScaleFactor); int iImageHeight = (int) Math.round(img.getHeight() * dScaleFactor); if (dScaleFactor <= 1.0d) { imgScale = getScaledDownInstance(img, iImageWidth, iImageHeight, hint, bHighQuality); } else { imgScale = getScaledUpInstance(img, iImageWidth, iImageHeight, hint, bHighQuality); } return imgScale; } protected BufferedImage getScaledDownInstance(BufferedImage img, int targetWidth, int targetHeight, Object hint, boolean higherQuality) { int type = (img.getTransparency() == Transparency.OPAQUE) ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB; BufferedImage ret = (BufferedImage) img; if (targetHeight > 0 || targetWidth > 0) { int w, h; if (higherQuality) { w = img.getWidth(); h = img.getHeight(); } else { w = targetWidth; h = targetHeight; } do { if (higherQuality && w > targetWidth) { w /= 2; if (w < targetWidth) { w = targetWidth; } } if (higherQuality && h > targetHeight) { h /= 2; if (h < targetHeight) { h = targetHeight; } } BufferedImage tmp = new BufferedImage(Math.max(w, 1), Math.max(h, 1), type); Graphics2D g2 = tmp.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint); g2.drawImage(ret, 0, 0, w, h, null); g2.dispose(); ret = tmp; } while (w != targetWidth || h != targetHeight); } else { ret = new BufferedImage(1, 1, type); } return ret; } protected BufferedImage getScaledUpInstance(BufferedImage img, int targetWidth, int targetHeight, Object hint, boolean higherQuality) { int type = BufferedImage.TYPE_INT_ARGB; BufferedImage ret = (BufferedImage) img; int w, h; if (higherQuality) { w = img.getWidth(); h = img.getHeight(); } else { w = targetWidth; h = targetHeight; } do { if (higherQuality && w < targetWidth) { w *= 2; if (w > targetWidth) { w = targetWidth; } } if (higherQuality && h < targetHeight) { h *= 2; if (h > targetHeight) { h = targetHeight; } } BufferedImage tmp = new BufferedImage(w, h, type); Graphics2D g2 = tmp.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint); g2.drawImage(ret, 0, 0, w, h, null); g2.dispose(); ret = tmp; tmp = null; } while (w != targetWidth || h != targetHeight); return ret; } } } 

这段代码大量借用了我的个人库代码,所以它可能有点复杂;)