JLabel 中的刷新图像不起作用
Posted
技术标签:
【中文标题】JLabel 中的刷新图像不起作用【英文标题】:Refreshing Image in JLabel doesnt work 【发布时间】:2014-02-16 01:54:26 【问题描述】:您好,我在刷新图片时遇到问题,已添加到 JLabel
。它类似于控制灯,为我们提供有关在线/离线状态的信息。当我们启动应用程序并且服务器开启时,它会调用此方法并将灯变为绿色。我们当然可以点击“离线”按钮,让它一直离线。然后灯是红色的。现在一切正常,但是当我们点击“上线”时,程序在线但图像仍然是红色的。在每个地方,它都由相同的方法调用。只是这个灯不起作用,因为连接和断开都可以正常工作。
我给你一些代码:
只改变图像的方法:
public void changeLight(String name)
BufferedImage imgtmp;
try
System.out.println("CHANGE LIGHT: "+name);
imgtmp = ImageIO.read(new File(name));
panelMenuOnline.remove(panelMenuOnlineLight);
panelMenuOnlineLight = new JLabel(new ImageIcon(imgtmp));
panelMenuOnline.add(panelMenuOnlineLight);
catch (IOException e)
e.printStackTrace();
同一类中的按钮定义:
panelMenuButOn = new Guzik("GO ONLINE")
@Override
public void actionPerformed(ActionEvent e)
if(!Pang.game.online)
Pang.game.haveToBeOffline = false;
if(Client.checkConnection())
JOptionPane.showMessageDialog(this,
"Successfully connected");
Pang.game.online=true;
changeLight(imgGREEN);
else
JOptionPane.showMessageDialog(this,
"Connection refused");
else
JOptionPane.showMessageDialog(this,
"Successfully disconnected");
setText("GO ONLINE");
Pang.game.haveToBeOffline = true;
Pang.game.online=false;
changeLight(imgRED);
;
我也有线程(如果我不让他离线)测试连接和更改控制灯:
public void run()
while(true)
Pang.game.online=Client.checkConnection();
if(Pang.game.online)
Pang.game.frame.panelMenuButOn.setText("GO OFFLINE");
Pang.game.frame.changeLight(Pang.game.frame.imgGREEN);
else
Pang.game.frame.panelMenuButOn.setText("GO ONLINE");
Pang.game.frame.changeLight(Pang.game.frame.imgRED);
//System.out.println("Checked = "+Pang.game.online);
try
Thread.sleep(1000);
catch (InterruptedException e)
e.printStackTrace();
【问题讨论】:
【参考方案1】:您不只是更改 JLabel 显示的图标,而是完全更改 JLabel,我建议您不要这样做。相反,...
在程序创建时读取您的图像并创建您的 ImageIcon,而不是每次您需要更改灯光时。 仅使用 一个 JLabel 来保存图标。 当你想改变灯光时,调用一个不需要字符串的方法。如果灯光仅处于 2 种状态,则布尔值可能会做得很好。然后在一个 JLabel 中换掉 ImageIcons。不要在不需要时更换 JLabels 中间程序。 这样的代码行:Pang.game.frame.panelMenuButOn.setText("GO OFFLINE");
,建议您使用静态字段和方法。如果是这样,您将需要重新配置您的程序,以便它不会这样做,以便它对大多数情况使用实例方法和字段。
我同意Ross Drew 的观点——您的所有Swing 调用都应仅在Swing 事件调度线程(或EDT)上进行。 1+ 他的回答。
例如,
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.EnumMap;
import javax.imageio.ImageIO;
import javax.swing.*;
@SuppressWarnings("serial")
public class StopLightApp extends JPanel
private static final String IMG_PATH = "http://urbannight.files.wordpress.com/2012/09/"
+ "red-orange-green-traffic-lights.jpg?w=300&h=240";
private static final int PAD = 13;
private JLabel stopLightLabel = new JLabel();
private EnumMap<LightColor, Icon> lightIconMap = new EnumMap<LightColor, Icon>(
LightColor.class);
private LightColor lightColor = LightColor.RED;
public StopLightApp() throws IOException
URL stopLightImgUrl = new URL(IMG_PATH);
BufferedImage stopLightImg = ImageIO.read(stopLightImgUrl);
for (int i = 0; i < LightColor.values().length; i++)
BufferedImage smlLightImg = specializedForThisImageGetSubImage(
stopLightImg, i);
Icon smlIcon = new ImageIcon(smlLightImg);
lightIconMap.put(LightColor.values()[i], smlIcon);
add(stopLightLabel);
stopLightLabel.setIcon(lightIconMap.get(lightColor));
stopLightLabel.setText(lightColor.getName());
stopLightLabel.setHorizontalTextPosition(SwingConstants.CENTER);
stopLightLabel.setVerticalTextPosition(SwingConstants.BOTTOM);
setBackground(Color.white);
setBorder(BorderFactory.createEmptyBorder(10, 60, 10, 60));
private BufferedImage specializedForThisImageGetSubImage(
BufferedImage stopLightImg, int i)
int x = PAD + (i * (stopLightImg.getWidth() - 2 * PAD)) / 3;
int y = PAD;
int w = (stopLightImg.getWidth() - 2 * PAD) / 3;
int h = stopLightImg.getHeight() - 2 * PAD;
BufferedImage smlLightImg = stopLightImg.getSubimage(x, y, w, h);
return smlLightImg;
public void setLightColor(LightColor lightColor)
this.lightColor = lightColor;
stopLightLabel.setIcon(lightIconMap.get(lightColor));
stopLightLabel.setText(lightColor.getName());
private static void createAndShowGui()
try
final StopLightApp stopLight = new StopLightApp();
JFrame frame = new JFrame("Stop Light App");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(stopLight);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
int delay = 1000;
new Timer(delay, new ActionListener()
int index = 0;
@Override
public void actionPerformed(ActionEvent e)
index++;
index %= LightColor.values().length;
stopLight.setLightColor(LightColor.values()[index]);
).start();
catch (IOException e)
e.printStackTrace();
public static void main(String[] args)
SwingUtilities.invokeLater(new Runnable()
public void run()
createAndShowGui();
);
enum LightColor
RED("Red"), YELLOW("Yellow"), GREEN("Green");
private String name;
private LightColor(String name)
this.name = name;
public String getName()
return name;
这创造了一种可以改变的光:
【讨论】:
...但我可以投票给你,恕我直言,这是这个问题的绝佳答案。 我一直在寻找该解决方案,但我找不到如何在标签中交换图标,因为我认为我必须删除一个图标并添加另一个? @user3233685:请看我上面的代码示例。您需要做的就是在 JLabel 上调用setIcon(Icon icon)
来交换图标,就是这样!
感谢您的解决方案 ;)) 一切正常!
@HovercraftFullOfEels :每次我看你的答案,我都会学到一些关于语言的新东西。出色的工作:-)以上是关于JLabel 中的刷新图像不起作用的主要内容,如果未能解决你的问题,请参考以下文章
java - JLabel setForeground 在 SwingWorker 中不起作用
除非我刷新,否则 jQuery mobile 中的 JavaScript 不起作用
完整功能中的ajax调用后刷新jquery mobile listview不起作用
通过更改 SwiftUI 中的 @State 变量来刷新视图不起作用