JButton 上的 Java ImageIcon 重复图像

标签 java swing jbutton setbackground

这篇文章的目的是弄清楚为什么它会在两个按钮上复制两个图像。这很奇怪,不应该发生。这是主要目标。然后它将找到解决方案。谢谢!

它的外观图片

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

我可以通过将 Jbutton 的背景颜色设置为透明来隐藏问题,但这没有解决问题。

为什么会这样? 我更担心两个图像在同一个 JButton 上,但还有另一个问题在查看图像时很容易注意到,我真的不知道如何解释。

最佳答案

在发布问题时,建议发布 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: 随着新添加的 mre,问题现在很清楚了:每个按钮显示两个图像一个在另一个之上。
删除 btn.setBackground(new Color(50,50,50,0));
后问题确实消失了 这可以用 "setBackground() doesn't read well on some platforms" 来解释摘自@trashgod 的回答。
可以按照此 answer 中的说明设置 LAF 来消除该问题。由@Andrew Thompsom 撰写。
这是一个 mre演示它。

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

(引自 JComponent#setBackground(Color) documentation 。)

编辑 2:

覆盖 paintComponent 的自定义 JButton 正常工作(具有透明颜色,其中 alfa 为 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) documentation状态:

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.

出于某种原因 JButton 没有。

关于JButton 上的 Java ImageIcon 重复图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60924036/

相关文章:

java - 如何使用 GridLayout 从 JFrame 获取组件?

java - 调整 JButton 大小会导致其消失

java - 使用 Outpan 的 JAVA API

java - 将java中的arraylist转换为c

java - split() 一个字符串到一个字符串数组,并且在 [0] 处没有得到空白

java - 将旧的 Netbeans 3.6 大型 Java 项目(2 GB 源代码)转换为新的 Netbeans 7 IDE

java - 如何更改JButton?

java - 通过 java 套接字发送文件时出错

java - 为什么顶层容器中的覆盖油漆如此糟糕?

java - 使用 nimbus 对 java swing 中的按钮进行 3D 效果