2012-07-19 68 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; 
    } 
}