java - JLabel 中刷新图像不起作用

标签 java image swing refresh jlabel

您好,我在刷新添加到 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(); 
        }

    }
}

最佳答案

您不仅仅是更改 JLabel 显示的图标,而是完全更改 JLabels,我建议您不要这样做。相反,...

  • 在程序创建时读取图像并创建图像图标,而不是每次需要更改灯光时。
  • 仅使用一个 JLabel 来保存图标。
  • 当您想要更改灯光时,调用不需要字符串的方法。如果灯仅处于两种状态,则 boolean 值可能会很好。然后交换一个 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;
   }
}

这会产生一种可以改变的光:

red light yellow light green light

关于java - JLabel 中刷新图像不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21343384/

相关文章:

java - 具有多个打印问题的硬币翻转程序

image - 重新着色图片广告以匹配网站主题

Java为JTextArea添加打字机效果

java - 进度条不变

Java 为 Integer 参数调用 String.valueOf(char[] data) 而不是 String.valueOf(int i) 并抛出 ClassCastException

java - 导入 AWTUtilities 时出错

python - matplotlib 在单个 pdf 页面中显示许多图像

java - JPanel 中的 Swing 计时器和动画

java - 除非整个盒子都填满,否则不要进入下一个 Activity

java - BlackBerry drawTexturedPath 旋转 将 anchor 移动到图像中心