Search code examples
javaswingmouseoverjbuttonimageicon

Darken JButton(s) on hover/click


ImageIcon backpackImageIcon = new ImageIcon("images/gui/button_backpack.png");
JButton backpackButton = new JButton();
backpackButton.setBounds(660,686,33,33);
backpackButton.setBorderPainted(false);
backpackButton.setFocusPainted(false);
backpackButton.setVisible(true);
backpackButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("B"), "backpackButtonPress");
backpackButton.getActionMap().put("backpackButtonPress", ClassBackpackButton);
backpackButton.setAction(ClassBackpackButton);
backpackButton.setIcon(backpackImageIcon);
backpackButton.setToolTipText("Backpack[B]");
panel.add(backpackButton);      

I have multiple buttons set up this exact way. What I was hoping to be able to do was to have them darken 10% on hover and maybe 20% on click. I tried to look around for how to do this but had no luck(only found javascript stuff). Sorry if this has been asked before and thanks for any help.

** EDIT **

I have tried to do this but it just turns the image blank:

BufferedImage bufferedImage = null;
try {
    bufferedImage = ImageIO.read(new File("images/gui/button_backpack.png"));
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
BufferedImage darkerBackpackBufferedImage = new BufferedImage(32, 32, BufferedImage.TYPE_BYTE_INDEXED);
RescaleOp op = new RescaleOp(1.3f, 0, null);
darkerBackpackBufferedImage = op.filter(bufferedImage, null);
ImageIcon darkerBackpackImageIcon = new ImageIcon((Image) darkerBackpackBufferedImage);
backpackButton.setRolloverIcon((ImageIcon) darkerBackpackImageIcon);

** EDIT ** with solution

here is the modified shiftColor function that I went with for anyone reading this above... good luck :)

public BufferedImage shiftColor(BufferedImage img, int rShift, int gShift, int bShift) {
    Color tmpCol;
    int tmpRed, tmpGreen, tmpBlue;
    for (int x = 0; x < img.getWidth(); x++) {
        for (int y = 0; y < img.getHeight(); y++) {
            tmpCol=new Color(img.getRGB(x,y));
            tmpRed = (tmpCol.getRed()-rShift < 0) ? 0 : tmpCol.getRed()-rShift; //if shifted color is less than 0 change to 0
            tmpGreen = (tmpCol.getGreen()-gShift < 0) ? 0 : tmpCol.getGreen()-gShift; //if shifted color is less than 0 change to 0
            tmpBlue = (tmpCol.getBlue()-bShift < 0) ? 0 : tmpCol.getBlue()-bShift; //if shifted color is less than 0 change to 0
            tmpCol=new Color(tmpRed, tmpGreen, tmpBlue);
            img.setRGB(x,y,tmpCol.getRGB());
        }
    }
    return img;
}

Solution

  • This function will return a BufferedImage with a color offset (ie. lighter/darker)

    public BufferedImage shiftColor(BufferedImage img, int rShift, int gShift,int bShift) {
        Color tmpCol;
        for (int x = 0; x < img.getWidth(); x++) {
            for (int y = 0; y < img.getHeight(); y++) {
                tmpCol=new Color(img.getRGB(x,y));
                tmpCol=new Color(tmpCol.getRed()-rShift,tmpCol.getGreen()-gShift,tmpCol.getBlue()-bShift);
                img.setRGB(x,y,tmpCol.getRGB());
            }
        }
        return img;
    }
    

    Even though this will work, I still recommend creating both the light and dark image in an image editor (ie. Photoshop) and loading both at startup. The above code will be process intensive and will slow your apps runtime.