2014-01-24 237 views
2

嗨,我有一个刷新图像的问题,添加到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(); 
     } 

    } 
} 

回答

5

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

  • 阅读您的图像,并在程序创建时创建ImageIcons,而不是每次需要更改光源。
  • 只使用一个 JLabel拿着图标。
  • 当你想改变灯光时,调用一个不需要String的方法。如果光线仅处于2种状态,布尔值可能会表现良好。然后在一个JLabel中换出ImageIcons。当不需要时,不要交换JLabels中间程序。
  • 这样的代码行:Pang.game.frame.panelMenuButOn.setText("GO OFFLINE");,建议您使用静态字段和方法。如果是这样,您将需要重新配置程序,以便它不会这样做,以便它为大多数情况使用实例方法和字段。
  • 我同意Ross Drew--所有的Swing调用只能在Swing Event Dispatch Thread(或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 lightyellow lightgreen light

+0

...但我可以给予好评你的,恕我直言,这是极好回答这个问题。 –

+0

我正在寻找解决方案,但我找不到如何交换标签中的图标,因为我想我必须删除一个图标并添加另一个图标? –

+0

@ user3233685:请参阅我上面的代码示例。所有你需要做的就是调用JLabel上的'setIcon(Icon icon)'来交换图标,就是这样! –