【问题标题】:Refreshing Image in JLabel doesnt workJLabel 中的刷新图像不起作用
【发布时间】: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(); 
        }

    }
}

【问题讨论】:

    标签: java image swing refresh jlabel


    【解决方案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 :每次我看你的答案,我都会学到一些关于语言的新东西。出色的工作:-)
    猜你喜欢
    • 2013-07-03
    • 2013-10-12
    • 2012-05-13
    • 2014-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多