2012-07-19 69 views
6

我试图加载相同的jlabel存储图像两次到一个网格布局面板,但不是创建图像的两个实例,图像只显示一次,然后移动。JLabel图像阵列

如何将pieces数组中的相同JLabel位置存储到boardLabels数组中的多个JLabel中。

谢谢:)

public static JPanel boardPanel = new JPanel(new GridLayout(4, 0)); 
public static JLabel pieces[] = new JLabel[2]; 
private static JLabel[] boardLabels = new JLabel[4]; 

public MainFrame() { 
    pieces[0] = new JLabel(new ImageIcon(System.getProperty("user.dir") + "/images/piece1.png")); 
    pieces[1] = new JLabel(new ImageIcon(System.getProperty("user.dir") + "/images/piece2.png")); 

    this.add(boardPanel); 
    displayGUIboard(); 
} 


public static void displayGUIboard() { 

    //ERROR - the label in pieces[0] is not copied into both boardLabels [0] and [1] 
    boardLabels[0] = pieces[0]; 
    boardLabels[1] = pieces[0]; 

    boardPanel.add(boardLabels[0]); 
    boardPanel.add(boardLabels[1]); 
} 

public static void main(String[] args) { 
    MainFrame frame = new MainFrame(); 
    frame.setVisible(true); 
    frame.setSize(600, 600); 
    frame.setLocationRelativeTo(null); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
} 

此使用ImageIcons的时候,但我想避免这种情况,因为更新电路板,我将不得不删除然后重新加载的JLabel工作

boardLabels[0] = new JLabel(pieces[1]); 
    boardLabels[1] = new JLabel(pieces[1]); 

。我宁愿更新已经加载的标签。

编辑 我以前试过,但它抛出一个空指针异常......

boardLabels[0].setIcon(pieces[1]); 
    boardLabels[1].setIcon(pieces[1]); 

    boardPanel.add(boardLabels[0]); 
    boardPanel.add(boardLabels[1]); 
+2

获得从路径相对于应用程序资源的'user.dir'是*** ***非常脆弱。由于这些图像显然是应用程序固有的,因此应将它们添加到Jar中作为[嵌入资源](http://stackoverflow.com/tags/embedded-resource/info)。 – 2012-07-19 03:35:04

回答

9

不要这样做,因为你不能多添加相同的组件不止一次到可视化容器。最好使用多个JLabels,但让它们使用相同的ImageIcon。 ImageIcons可多次使用轻松:

public MainFrame() { 
    pieceIcon[0] = new ImageIcon(System.getProperty("user.dir") + 
     "/images/piece1.png"); 
    pieceIcon[1] = new ImageIcon(System.getProperty("user.dir") + 
     "/images/piece2.png"); 

    this.add(boardPanel); 
    displayGUIboard(); 
} 


public void displayGUIboard() { 
    boardPanel.add(new JLabel(pieceIcon[0]); 
    boardPanel.add(new JLabel(pieceIcon[0]); 
} 

顺便说一句:请注意,您的变量没有应该是静态的。

编辑:关于您最近编辑:

使用ImageIcons时,该工作

boardLabels[0] = new JLabel(pieces[1]); 
boardLabels[1] = new JLabel(pieces[1]); 

,但我想避免这种情况,因为更新电路板,我将有删除然后重新加载JLabels。我宁愿只更新已加载的标签。”

解决方案
不,你不必在所有改变的JLabel。保持你的JLabel他们在哪里,但简单地交换他们持有的图标使用的JLabel setIcon(...)方法。

编辑
另外,不要混淆对象的变量,即使你创造了一堆JLabel的变量,如果他们都指向同一个对象的JLabel,你仍然不能添加一个JLabel对象不止一次到一个容器。

编辑幽州:

的代码是一个游戏的显示功能的一部分。一组整数将表示被解释的板(但不在上面的代码中),并且正确的Jlabel图像将被放置到网格布局面板中以显示板的gui。我已经得到了显示的代码工作正常,但在我目前的版本它删除的JLabel从电路板然后创建新的JLabel(件...)...但我宁愿它本身从整数数组更新,而不是删除标签,读取数组,然后重新创建标签。

因此,创建一个使用GridLayout并使用不变的JLabel填充它的JPanel。然后只需根据int数组中保存的值更改JLabels所保存的图标。您可以创建一个简化和自动化此过程的方法。

编辑有关:

编辑我以前试过,但它抛出一个空指针异常。

然后解决这个问题,就像任何NPE。找出哪条线引发NPE,检查线上的变量,至少有一个为空,然后修复它,以便在尝试使用它之前初始化变量。

编辑
例如:

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.GridLayout; 
import java.awt.image.BufferedImage; 

import javax.swing.*; 

@SuppressWarnings("serial") 
public class GridExample extends JPanel { 
    public static final int[][] MAP = { 
     {1, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2}, 
     {1, 1, 0, 0, 2, 2, 2, 2, 2, 2, 2}, 
     {1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2}, 
     {1, 1, 1, 0, 0, 2, 2, 2, 2, 2, 2}, 
     {1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2}, 
     {1, 1, 1, 0, 0, 0, 2, 2, 2, 2, 2}, 
     {1, 1, 0, 0, 0, 2, 2, 2, 2, 2, 2}, 
     {1, 1, 1, 0, 0, 0, 2, 2, 2, 2, 2}, 
     {1, 1, 1, 1, 1, 0, 0, 0, 0, 2, 2}, 
     {1, 1, 1, 1, 1, 0, 0, 0, 2, 2, 2}, 
     {1, 1, 1, 1, 1, 1, 0, 0, 0, 2, 2} 
    }; 

    public static final Color[] COLORS = {}; 
    private JLabel[][] labelGrid = new JLabel[MAP.length][MAP[0].length]; 

    public GridExample() { 
     setLayout(new GridLayout(MAP.length, MAP[0].length)); 
     for (int r = 0; r < labelGrid.length; r++) { 
     for (int c = 0; c < labelGrid[r].length; c++) { 
      labelGrid[r][c] = new JLabel(); 
      labelGrid[r][c].setIcon(Ground.getGround(MAP[r][c]).getIcon()); 
      add(labelGrid[r][c]);    
     } 
     } 
    } 

    private static void createAndShowGui() { 
     GridExample mainPanel = new GridExample(); 

     JFrame frame = new JFrame("GridExample"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

enum Ground { 
    DIRT(0, new Color(205,133, 63)), GRASS(1, new Color(0, 107, 60)), 
    WATER(2, new Color(29, 172, 214)); 
    private int value; 
    private Color color; 
    private Icon icon; 

    private Ground(int value, Color color) { 
     this.value = value; 
     this.color = color; 

     icon = createIcon(color); 
    } 

    private Icon createIcon(Color color) { 
     int width = 24; // how to use const in enum? 
     BufferedImage img = new BufferedImage(width, width, BufferedImage.TYPE_INT_ARGB); 
     Graphics g = img.getGraphics(); 
     g.setColor(color); 
     g.fillRect(0, 0, width, width); 
     g.dispose(); 
     return new ImageIcon(img); 
    } 

    public int getValue() { 
     return value; 
    } 

    public Color getColor() { 
     return color; 
    } 

    public Icon getIcon() { 
     return icon; 
    } 

    public static Ground getGround(int value) { 
     for (Ground ground : Ground.values()) { 
     if (ground.getValue() == value) { 
      return ground; 
     } 
     } 
     return null; 
    } 

} 

其中显示了一个GUI网格:
enter image description here

+0

我创建boardLabel阵列中的多个的JLabel,但这些不与从自的JLabel片阵列中的片阵列相同的JLabel分配不能被添加两次,正确? – user1334130 2012-07-19 03:26:54

+0

哈哈!发布相同的东西 – user1334130 2012-07-19 03:31:17

+0

因此,它不可能更新一定数量的JLabels,因为它们都指向不起作用的同一个对象。 – user1334130 2012-07-19 03:33:22

10

为了便于比较,我已经重新分解@ HFOE的example使Ground implements Icon和索引数组由values()返回。作为value是一个实现细节,int[][] MAP可以替换为Ground[][] MAP

更新:这种变化说明Ground[][] MAP,并增加了TexturePaint

enter image description here

import java.awt.Color; 
import java.awt.Component; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.GridLayout; 
import java.awt.TexturePaint; 
import java.awt.geom.Rectangle2D; 
import java.awt.image.BufferedImage; 
import java.util.Random; 
import javax.swing.*; 

/** @see https://stackoverflow.com/a/11556441/230513 */ 
public class GridExample extends JPanel { 

    public static final Ground[][] MAP = { 
     {Ground.GRASS, Ground.GRASS, Ground.DIRT, Ground.WATER, Ground.WATER}, 
     {Ground.GRASS, Ground.DIRT, Ground.CITY, Ground.WATER, Ground.WATER}, 
     {Ground.GRASS, Ground.DIRT, Ground.CITY, Ground.WATER, Ground.WATER}, 
     {Ground.GRASS, Ground.DIRT, Ground.DIRT, Ground.DIRT, Ground.WATER}, 
     {Ground.GRASS, Ground.GRASS, Ground.DIRT, Ground.WATER, Ground.WATER}, 
    }; 
    private JLabel[][] labelGrid = new JLabel[MAP.length][MAP[0].length]; 

    public GridExample() { 
     setLayout(new GridLayout(MAP.length, MAP[0].length)); 
     for (int r = 0; r < labelGrid.length; r++) { 
      for (int c = 0; c < labelGrid[r].length; c++) { 
       labelGrid[r][c] = new JLabel(); 
       labelGrid[r][c].setIcon(MAP[r][c]); 
       add(labelGrid[r][c]); 
      } 
     } 
    } 

    private static void createAndShowGui() { 
     GridExample mainPanel = new GridExample(); 
     JFrame frame = new JFrame("GridExample"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       createAndShowGui(); 
      } 
     }); 
    } 
} 

enum Ground implements Icon { 

    DIRT(new Color(205, 133, 63)), GRASS(new Color(0, 107, 60)), 
    WATER(new Color(29, 172, 214)), CITY(Color.lightGray); 
    private static final int SIZE = 42; 
    private Random random = new Random(); 
    private TexturePaint paint; 

    private Ground(Color color) { 
     this.paint = initPaint(color); 
    } 

    private TexturePaint initPaint(Color color) { 
     BufferedImage image = new BufferedImage(
      SIZE, SIZE, BufferedImage.TYPE_INT_ARGB); 
     Rectangle2D.Double rect = new Rectangle2D.Double(0, 0, SIZE, SIZE); 
     for (int row = 0; row < SIZE; row++) { 
      for (int col = 0; col < SIZE; col++) { 
       if (random.nextBoolean()) { 
        image.setRGB(col, row, color.getRGB()); 
       } else { 
        if (random.nextBoolean()) { 
         image.setRGB(col, row, color.darker().getRGB()); 
        } else { 
         image.setRGB(col, row, color.brighter().getRGB()); 
        } 
       } 
      } 
     } 
     return new TexturePaint(image, rect); 
    } 

    @Override 
    public void paintIcon(Component c, Graphics g, int x, int y) { 
     Graphics2D g2d = (Graphics2D) g; 
     g2d.setPaint(paint); 
     g.fillRect(0, 0, SIZE, SIZE); 
    } 

    @Override 
    public int getIconWidth() { 
     return SIZE; 
    } 

    @Override 
    public int getIconHeight() { 
     return SIZE; 
    } 
}