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 变量来刷新视图不起作用

快速刷新在 Visual Studio Code 中的 React Native 中不起作用

useEffect 中的套接字连接事件在创建组件时不起作用,但在 React 中刷新页面后起作用