Java JButton 上的 ImageIcon 重复图像
Java ImageIcon on JButton duplicates image
这个 post 的目的是找出为什么它在两个按钮上复制两个图像。这很奇怪,不应该发生。这是主要目标。然后它将找到解决方案。谢谢!
外观图片
我做了一个 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();
}
}
我可以隐藏问题,方法是不将Jbuttons的背景颜色设置为透明,但是没有't解决问题
为什么会这样?
我更担心两个图像在同一个 JButton 上,但还有一个问题在查看图像时很容易注意到,我真的不知道如何解释。
当 post 提出问题时,建议 post 一个 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));
后问题确实消失了
这可以用来自@trashgod 答案的 "setBackground() doesn't read well on some platforms" 来解释。
这个问题可以通过设置 LAF 来解决,正如@Andrew Thompsom 在 answer 中所解释的那样。
这是一个 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
没有。
这个 post 的目的是找出为什么它在两个按钮上复制两个图像。这很奇怪,不应该发生。这是主要目标。然后它将找到解决方案。谢谢!
外观图片
我做了一个 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();
}
}
我可以隐藏问题,方法是不将Jbuttons的背景颜色设置为透明,但是没有't解决问题
为什么会这样? 我更担心两个图像在同一个 JButton 上,但还有一个问题在查看图像时很容易注意到,我真的不知道如何解释。
当 post 提出问题时,建议 post 一个 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));
后问题确实消失了 这可以用来自@trashgod 答案的 "setBackground() doesn't read well on some platforms" 来解释。
这个问题可以通过设置 LAF 来解决,正如@Andrew Thompsom 在 answer 中所解释的那样。
这是一个 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
没有。