3

The goal of this post is to figure out why it is duplicating both images on both buttons. It is VERY odd and should not be happening. That is the main goal. Then it would be finding a solution. Thank you!

Image of what it looks like

enter image description here

I've made an MRE

It outputs both images on both buttons and I don't know why.

import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GameManager extends JFrame{

    private final   Map <String, String> images = new HashMap<>(2);

    GameManager()
    {
        images.put("Articuno", "https://i.ya-webdesign.com/images/articuno-transparent-pokemon-xy-17.gif");
        images.put("Rayquaza", "https://play.pokemonshowdown.com/sprites/ani-back-shiny/rayquaza.gif");

        JPanel pnlPokemonInParty = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        //Why does it put both images on both buttons? It actually sets the images on top of one another.
        //You can tell which image is in the front and which is behind the other.
        //I'm setting the buttons to be transparent. Setting the buttons to not be transparent will cover the the image below it,
        //that's how I know they're being stacked on top of one another.
        JButton btn1 = gifBtn("Articuno");
        JButton btn2 = gifBtn("Rayquaza");
        c.gridx = 0;
        pnlPokemonInParty.add(btn1, c);
        c.gridx = 1;
        pnlPokemonInParty.add(btn2, c);
        this.add(pnlPokemonInParty);
        this.pack();
        this.setVisible(true);
    }
    public JButton gifBtn(String name)
    {
        final JButton btn = new JButton();
        URL url = null;
        try {
            url = new URL(images.get(name));
        } catch (MalformedURLException ex) {
            ex.printStackTrace();
        }
        Icon icon = new ImageIcon(url);
        btn.setIcon(icon);
        btn.setBackground(new Color(50,50,50,0));
        return btn;
    }

    public static void main(String[] args)
    {
        GameManager gameManager = new GameManager();
    }
}

I can hide the problem by not setting the background color of the Jbuttons to be transparent but that doesn't solve the problem.

Why does this happen? I'm more so worried about the two images being on the same JButton, but there is another issue that is easily noticeable when looking at the image that I don't really know how to explain.

Bwizz
  • 81
  • 6

1 Answers1

2

When posting a question it is recommended to post an MRE like the following:

import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GameManager extends JFrame{

    private final   Map <String, String> images = new HashMap<>(2);

        GameManager()
        {
            images.put("Articuno", "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/256x256/Box_Green.png");
            images.put("Rayquaza", "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/256x256/Box_Red.png");

            JPanel pnlPokemonInParty = new JPanel(new GridBagLayout());
                GridBagConstraints c = new GridBagConstraints();
                JButton btn1 = gifBtn("Articuno");
                JButton btn2 = gifBtn("Rayquaza");
                c.gridx = 0;
                pnlPokemonInParty.add(btn1, c);
                c.gridx = 1;
                pnlPokemonInParty.add(btn2, c);
                this.add(pnlPokemonInParty);
                this.pack();
                this.setVisible(true);
        }
         public JButton gifBtn(String name)
         {
                final JButton btn = new JButton();
                URL url = null;
                try {
                    url = new URL(images.get(name));
                } catch (MalformedURLException ex) {
                    ex.printStackTrace();
                }
                Icon icon = new ImageIcon(url);
                btn.setIcon(icon);
                btn.setBackground(new Color(50,50,50,0));
                return btn;
         }

    public static void main(String[] args)
    {
            GameManager gameManager = new GameManager();
    }
 }

The code works fine using publicly available images so it suggests that there is a problem with the local resource.
MRE makes helping much easier and it is a powerful debugging tool. It many case, while preparing one, you are likely to find the problem.


Edit 1: With the newly add mre the problem is clear now: each button shows the two images one on top of the other.
The problem indeed disappears when removing btn.setBackground(new Color(50,50,50,0));
This may be explained by "setBackground() doesn't read well on some platforms" taken from @trashgod answer.
The problem can be eliminated by setting LAF as explained in this answer by @Andrew Thompsom.
Here is an mre demonstrating it.

It is up to the look and feel to honor this property, some may choose to ignore it.

(Quoted from JComponent#setBackground(Color) documentation.)

Edit 2:

A custom JButton which overrides paintComponent works properly (with transparent color where alfa is to 0 like new Color(50,50,50,0) or any other color):

class Main extends JFrame{

    private final Map <String, String> images = new HashMap<>();

    Main()
    {
        images.put("Articuno", "https://66.media.tumblr.com/d9105814c15295196a3dbe75c32ba1a0/tumblr_oagpklvBGf1scncwdo1_400.gif");
        images.put("Rayquaza", "https://play.pokemonshowdown.com/sprites/ani-back-shiny/rayquaza.gif");
        images.put("GreenCircle", "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/128x128/Circle_Green.png");
        images.put("RedBox", "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/256x256/Box_Red.png");

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().setBackground(Color.WHITE);
        this.setLayout(new FlowLayout());
        this.add(gifBtn("GreenCircle"));
        this.add(gifBtn("RedBox"));
        this.add(gifBtn("Articuno"));
        this.add(gifBtn("Rayquaza"));
        this.pack();
        this.setVisible(true);
    }

    public JButton gifBtn(String name)
    {
       JButton btn = new CustomButton();
        try {
            URL url = new URL(images.get(name));
            btn.setIcon(new ImageIcon(url));
        } catch (MalformedURLException ex) { ex.printStackTrace();   }

        return btn;
    }

    public static void main(String[] args) throws Exception
    {
        new Main();
    }
}

class CustomButton extends JButton{

    private final Color bgColor = new Color(255,192,203,0);

    public CustomButton() {
        //setBorderPainted(false);  //optioal
        setContentAreaFilled(false);
        setOpaque(false);
    }

    @Override
    public void paintComponent(Graphics g){
        g.setColor(bgColor);
        Rectangle r = g.getClipBounds();
        g.fillRect(r.x, r.y, r.width, r.height);
        super.paintComponent(g);
    }
}

JComponent#setBackground(Color) documentation states:

Direct subclasses of JComponent must override paintComponent to honor this property. It is up to the look and feel to honor this property, some may choose to ignore it.

from some reason JButton does not.

c0der
  • 18,467
  • 6
  • 33
  • 65
  • Your code uses two images that are the same size and shape. You wouldn't be able to tell if the images where being outputted to both buttons on top of one another. I tried your code with gifs from the web and the problem still persists. Thank you for helping me with the MRE. – Bwizz Mar 31 '20 at 21:19
  • With the newly add mre the problem is clear now. See my edit. – c0der Apr 01 '20 at 06:13
  • Again your MRE shows two images that are the same size. To speak more specifically "they are" different sizes but because you are using a border layout, it is setting the image that is behind the one on top, to the same size as the one on top. After switching out the images with actual gifs that are different sizes and putting them in a flow layout I can still see the problem. On top of that, the solution you provided overwrites the background of the buttons to not be transparent which is not a solution. In fact, it is the opposite. I could achieve that by not making the buttons transparent.Ty – Bwizz Apr 01 '20 at 21:24
  • Ran out of space in my last comment... The goal of this post is to figure out why it is duplicating both images on both buttons. It is VERY odd and should not be happening. That is the main goal. Then it would be finding a solution. How can I link the MRE I made with the new changes demonstrating the problem without changing the post from what it is? https://repl.it/repls/SwelteringMuddyIntelligence I tried doing what you did, so please let me know if it doesn't work. Thank you. – Bwizz Apr 01 '20 at 21:37
  • _Again your MRE shows two images that are the same size_ no it does not. _ because you are using a border layout_ I get exactly the same with GridbagLayout. The MRE you linked does show a painting problem, but a different one. Try running it without setting LAF and see the difference. – c0der Apr 02 '20 at 04:28