Java ImageIcon на JButton дублирует изображение - PullRequest
2 голосов
/ 30 марта 2020

Цель этого поста - выяснить, почему он дублирует оба изображения на обеих кнопках. Это очень странно и не должно происходить. Это главная цель. Тогда было бы найти решение. Спасибо!

Изображение того, как оно выглядит

enter image description here

Я сделал MRE

Он выводит оба изображения на обе кнопки, и я не знаю почему.

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

Я могу скрыть проблему с помощью не , устанавливающей цвет фона кнопок J прозрачным, но который не решает проблема.

Почему это происходит? Меня больше беспокоит то, что два изображения находятся на одном и том же JButton, но есть еще одна проблема, которую легко заметить, глядя на изображение, которое я не знаю, как объяснить.

1 Ответ

2 голосов
/ 30 марта 2020

При публикации вопроса рекомендуется опубликовать MRE , как показано ниже:

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

Код работает нормально, используя общедоступные изображения, поэтому он предполагает, что существует проблема с местный ресурс. MRE значительно облегчает помощь и является мощным средством отладки. Во многих случаях при подготовке вы, вероятно, найдете проблему.


Редактировать 1: С новым добавлением теперь проблема ясна: каждая кнопка отображает два изображения друг над другом.
Проблема действительно исчезает при удалении btn.setBackground(new Color(50,50,50,0)); Это может быть объяснено «setBackground () плохо читается на некоторых платформах» взято из ответа @trashgod. Эту проблему можно устранить, установив LAF, как описано в этом ответе @Andrew Thompsom. Вот mre демонстрирующий это.

Соблюдение этого свойства зависит от внешнего вида, некоторые могут игнорировать его.

(Цитируется из JComponent#setBackground(Color) документация * 1027) *.)

Редактировать 2:

Пользовательский JButton, который переопределяет paintComponent, работает правильно (с прозрачным цветом, где альфа равен 0, например new Color(50,50,50,0) или любой другой цвет):

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) документация состояния:

Прямые подклассы JComponent должны переопределить paintComponent, чтобы соблюдать это свойство. Это зависит от внешнего вида, чтобы почитать это свойство, некоторые могут проигнорировать его.

по какой-то причине JButton нет.

...