2012-07-19 41 views
6

Estoy tratando de cargar la misma imagen jlabel almacenada dos veces en un panel de distribución de cuadrícula, sin embargo, en lugar de crear dos instancias de la imagen, la imagen solo se muestra una vez que se mueve.JLabel images array

¿Cómo puedo almacenar la misma posición de JLabel en el conjunto de piezas en más de un JLabel en el conjunto de etiquetas de placa?

Gracias :)

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

Esto funciona

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

cuando se utiliza ImageIcons, pero quiero evitar esto ya que para actualizar la tarjeta de E tendrá que quitar a continuación, volver a cargar los JLabels. Prefiero simplemente actualizar las etiquetas ya cargadas.

edición He intentado esto antes, pero es una excepción de puntero nulo ...

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

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

Obtener un recurso de aplicación de una ruta relativa a la 'user.dir' es muy *** *** frágil. Dado que estas imágenes son aparentemente inherentes a la aplicación, deben agregarse al Jar como [recurso incrustado] (http://stackoverflow.com/tags/embedded-resource/info). –

Respuesta

9

No hacer esto ya no se puede agregar el mismo componente más de una vez a una contenedor visualizado. Es mejor usar varios JLabels pero hacer que usen el mismo ImageIcon. ImageIcons se pueden utilizar más de una vez con facilidad:

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

Como acotación al margen: en cuenta que ninguno de las variables debe ser estática.

Editar: con respecto a su reciente edición:

Esto funciona

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

cuando se utiliza ImageIcons, pero quiero evitar esto, ya que para actualizar el tablero tendré para eliminar y luego volver a cargar los JLabels. Yo preferiría simplemente actualizar las etiquetas ya cargadas."

Solución
No, no tiene que cambiar JLabels en absoluto. Mantenga sus JLabels donde están, sino simplemente cambiar los iconos que sean titulares utilizando el método de JLabel setIcon(...).

Editar
Además, no hay que confundir con las variables de objetos. Incluso si se crea un montón de variables JLabel, si todos ellos se refieren al mismo objeto JLabel, todavía no se puede agregar un objeto JLabel más de una vez a un contenedor.

Editar usted Estado:

El código es una parte de la función de visualización para un juego.Una matriz de enteros representará la placa que se interpreta (pero no en el código anterior) y las imágenes correctas de Jlabel se colocarán en un panel de distribución de cuadrícula para mostrar la interfaz gráfica de la placa. He conseguido que el código de la pantalla funcione bien, pero en mi versión actual elimina las jlabels de la placa y luego crea nuevas JLabels (pieza ...) ... pero preferiría que se actualizase a sí misma de la matriz entera en lugar de eliminarla las etiquetas, leyendo la matriz y luego recreando las etiquetas.

Por lo tanto, cree un JPanel que use GridLayout y llénelo con JLabels inalterables. Luego simplemente cambie los íconos que tienen las JLabels en función de los valores mantenidos por la matriz int. Puede crear un método que simplifique y automatice este proceso.

Editar respecto:

edición he intentado esto antes, pero se produce una excepción de puntero nulo.

Luego solucione esto como lo haría con cualquier NPE. Averigüe qué línea arroja el NPE, verifique las variables en la línea, al menos uno es nulo, y luego corríjalo para que inicialice la variable antes de intentar usarla.

Editar
por ejemplo:

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

} 

que muestra una cuadrícula de interfaz gráfica de usuario:
enter image description here

+0

Creé varios JLabels en la matriz boardLabel, pero estos no están siendo asignados con la misma JLabel de la matriz de piezas ya que los Jlabels en la matriz de piezas no se pueden agregar dos veces, ¿correcto? – user1334130

+0

¡Ja ja! publicó lo mismo – user1334130

+0

Por lo tanto, sería imposible actualizar una cantidad establecida de JLabels ya que todos apuntan al mismo objeto que no funciona. – user1334130

10

Para la comparación, he re-factorizar @ HFOE de example modo que Ground implements Icon y los índices de las matriz devuelta por values(). Como value es un detalle de implementación, int[][] MAP podría ser Ground[][] MAP.

Actualización: Esta variación ilustra Ground[][] MAP y agrega 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; 
    } 
}