Applying color to a transparent region of a JButton image - but not to its container

I have a circular JButton built using a circular PNG image with a transparent area.

I want to fill the transparent area of ​​the JButton image with the specified color, but not something other than the opaque background color of the JPanel that contains the JButton. I want to do this programmatically in Java, rather than providing pre-colored images from a graphics package.

I got to the code below, which simply allows the orange background of the opaque panel to color the transparent area. However, I can’t understand how to save the panel background as orange, but fill the image transparency with, say, blue (or another color for rollover and pressed effects).

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://features.advisorwebsites.com/sites/default/files/users/AdvisorWebsitesFeatures/icones/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). , , , ?

+1
2

paintComponent() JButton

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);

        }

    }

:

enter image description here

EDIT:

, 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);

        }

    }
+2

, , , , , , AlphaComposite...

, , ...

Original Masked

  • , ( )
  • , ()
  • , , .
  • "", , "" .
  • "" , .
  • , , .

: "" "", JButton, ...

...

Usual

...

Rollover

, - , , 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;
        }
    }

}

, ;)

+1

Source: https://habr.com/ru/post/1669125/


All Articles