2012-07-19 13 views
6

Sto provando a caricare due volte la stessa immagine memorizzata in jlabel in un pannello di griglia, ma invece di creare due istanze dell'immagine, l'immagine viene visualizzata solo una volta e poi spostata.JLabel images array

Come posso memorizzare la stessa posizione di JLabel nell'array di pezzi in più di una JLabel nell'array boardLabels.

Grazie :)

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); 
} 

Questo funziona

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

quando si utilizza ImageIcons, ma voglio evitare questo dal momento che per aggiornare la scheda dovrò rimuovere quindi ricaricare le JLabels. Preferirei semplicemente aggiornare le etichette già caricate.

modificare Ho provato questo prima, ma genera un'eccezione di puntatore nullo ...

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

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

Ottenere una risorsa un'applicazione da un percorso relativo alla cartella 'user.dir' è molto *** *** fragile. Poiché queste immagini sono apparentemente inerenti all'app, devono essere aggiunte a Jar come [risorsa incorporata] (http://stackoverflow.com/tags/embedded-resource/info). –

risposta

9

Non fare questo in quanto non è possibile aggiungere lo stesso componente più di una volta ad un contenitore visualizzato Meglio usare più JLabels ma farli usare lo stesso ImageIcon. ImageIcons possono essere utilizzati più di una volta con facilità:

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]); 
} 

Per inciso: notare che nessuno delle variabili deve essere statico.

Edit: per quanto riguarda il recente modifica:

questo funziona

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

quando si utilizza ImageIcons, ma voglio evitare questo dal momento che per aggiornare la scheda avrò per rimuovere quindi ricaricare i JLabels. Io preferirei di aggiornare solo le etichette già caricate."

Soluzione
No, non c'è bisogno di cambiare JLabels a tutti. Tenere le JLabels dove sono, ma semplicemente scambiare le icone che sono titolari utilizzando il metodo JLabel setIcon(...).

Modifica
Inoltre, non confondere le variabili con gli oggetti. anche se si crea un gruppo di variabili JLabel, se tutti fanno riferimento allo stesso oggetto JLabel, non è ancora possibile aggiungere un oggetto JLabela più di una volta in un contenitore.

Modifica È stato:

Il codice è una parte della funzione di visualizzazione per un gioco.Un array di numeri interi rappresenterà la scheda che viene interpretata (ma non nel codice precedente) e le immagini Jlabel corrette verranno posizionate in un pannello di gridlayout per visualizzare la GUI della scheda. Ho ottenuto il codice di visualizzazione per funzionare bene, ma nella mia versione attuale rimuove i jlabels dalla scheda quindi crea nuovi JLabels (pezzo ...) ... ma preferirei aggiornarsi dalla matrice di interi piuttosto che rimuovere le etichette, leggendo l'array, quindi ricreando le etichette.

Quindi creare un JPanel che utilizza GridLayout e riempirlo con JLabels invariabili. Quindi modifica semplicemente le icone contenute in JLabels in base ai valori contenuti nell'array int. È possibile creare un metodo che semplifica e automatizza questo processo.

Edit per quanto riguarda:

modificare Ho provato questo prima, ma genera un'eccezione puntatore nullo.

Quindi risolvere questo come si farebbe con qualsiasi NPE. Scopri quale linea lancia l'NPE, controlla le variabili sulla linea, almeno una è nullo, quindi correggila in modo da inizializzare la variabile prima di provare ad usarla.

Modifica
ad esempio:

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; 
    } 

} 

Che mostra una griglia GUI:
enter image description here

+0

Ho creato più JLabels nell'array boardLabel, ma questi non vengono assegnati con lo stesso JLabel dall'array del pezzo poiché i Jlabels nell'array pezzo non possono essere aggiunti due volte, corretto? – user1334130

+0

Ah ah! postato la stessa cosa – user1334130

+0

Quindi sarebbe impossibile aggiornare una quantità stabilita di JLabels poiché tutti puntano allo stesso oggetto che non funziona. – user1334130

10

Per confronto, ho ri-scomposto @ HFOE di example in modo che Ground implements Icon e indicizza i array restituito da values(). Come value è un dettaglio di implementazione, int[][] MAP potrebbe invece essere Ground[][] MAP.

Aggiornamento: questa variazione illustra Ground[][] MAP e aggiunge 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; 
    } 
}