JButton 上的 Java ImageIcon 重复图像

问题描述 投票:0回答:1

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

它的样子的图像

我已经做了 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 上,但是在查看图像时,还有另一个问题很容易注意到,我真的不知道如何解释......我认为在每个重绘周期中将 gif 的当前帧绘制到 gif 的每一帧的相同图像上,因此您可以看到 gif 的当前帧以及所有先前绘制的帧。如果在每个重绘周期创建一个新的 BufferedImage 并将当前帧绘制到该图像上,我认为这可以解决问题。

java swing jbutton setbackground
1个回答
2
投票

发布问题时,建议发布 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() 在某些平台上读起来不好” 摘自 @trashgod 答案来解释。
这个问题可以通过设置 LAF 来消除,如@Andrew Thompsom 的answer 中所述。
这是一个 mre 演示它。

尊重此属性取决于外观和感觉,有些人可能会 选择忽略它。

(引自

JComponent#setBackground(Color)
文档。)

编辑2:

覆盖

JButton
的自定义
paintComponent
可以正常工作(透明颜色,其中 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)
文档指出:

JComponent 的直接子类必须重写 PaintComponent 以支持此属性。 尊重这个属性取决于外观和感觉,有些人可能会选择忽略它。

出于某种原因

JButton
没有。

© www.soinside.com 2019 - 2024. All rights reserved.