Actualizar una imagen contenida en un JLabel – problemas

La parte de la aplicación que actualmente tengo problemas para llegar al trabajo es poder desplazarme y mostrar una lista de imágenes, una a la vez. Obtengo un directorio del usuario, en cola de todos los archivos en ese directorio, y luego cargando una matriz de solo jpegs y pngs. A continuación, deseo actualizar un JLabel con la primera imagen y proporcionar los botones anteriores y siguientes para desplazarse y mostrar cada imagen sucesivamente. Cuando trato de mostrar la segunda imagen, no se actualiza … Esto es lo que tengo hasta ahora:

public class CreateGallery { private JLabel swingImage; 

El método que estoy usando para actualizar la imagen:

 protected void updateImage(String name) { BufferedImage image = null; Image scaledImage = null; JLabel tempImage; try { image = ImageIO.read(new File(name)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // getScaledImage returns an Image that's been resized proportionally to my thumbnail constraints scaledImage = getScaledImage(image, THUMB_SIZE_X, THUMB_SIZE_Y); tempImage = new JLabel(new ImageIcon(scaledImage)); swingImage = tempImage; } 

Luego en mi método createAndShowGUI que pone el swingImage en …

 private void createAndShowGUI() { //Create and set up the window. final JFrame frame = new JFrame(); // Miscellaneous code in here - removed for brevity // Create the Image Thumbnail swingImage and start up with a default image swingImage = new JLabel(); String rootPath = new java.io.File("").getAbsolutePath(); updateImage(rootPath + "/images/default.jpg"); // Miscellaneous code in here - removed for brevity rightPane.add(swingImage, BorderLayout.PAGE_START); frame.add(rightPane, BorderLayout.LINE_END); 
 public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { UIManager.put("swing.boldMetal", Boolean.FALSE); new CreateGalleryXML().createAndShowGUI(); } }); } 

Si ha llegado hasta aquí, la primera imagen es mi default.jpg, y una vez que obtengo el directorio e identifico la primera imagen en ese directorio, allí es donde falla cuando bash actualizar el swingImage. Ahora, he intentado oscilar Image.setVisible () y swingImage.revalidate () para intentar forzarlo a volver a cargar. Supongo que es mi tempImage = new JLabel esa es la causa raíz. Pero no estoy seguro de cómo convertir mi Imagen Buffered o Imagen a un JLabel para simplemente actualizar swingImage.

En lugar de crear una New Instance de JLabel para cada Image , simplemente use el método JLabel # setIcon (…) de JLabel para cambiar la imagen.

Un pequeño progtwig de muestra:

 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class SlideShow extends JPanel { private int i = 0; private Timer timer; private JLabel images = new JLabel(); private Icon[] icons = {UIManager.getIcon("OptionPane.informationIcon"), UIManager.getIcon("OptionPane.errorIcon"), UIManager.getIcon("OptionPane.warningIcon")}; private ImageIcon pictures1, pictures2, pictures3, pictures4; private ActionListener action = new ActionListener() { public void actionPerformed(ActionEvent ae) { i++; System.out.println(i); if(i == 1) { pictures1 = new ImageIcon("image/caIcon.png"); images.setIcon(icons[i - 1]); System.out.println("picture 1 should be displayed here"); } if(i == 2) { pictures2 = new ImageIcon("image/Keyboard.png"); images.setIcon(icons[i - 1]); System.out.println("picture 2 should be displayed here"); } if(i == 3) { pictures3 = new ImageIcon("image/ukIcon.png"); images.setIcon(icons[i - 1]); System.out.println("picture 3 should be displayed here"); } if(i == 4) { pictures4 = new ImageIcon("image/Mouse.png"); images.setIcon(icons[0]); System.out.println("picture 4 should be displayed here"); } if(i == 5) { timer.stop(); System.exit(0); } revalidate(); repaint(); } }; public SlideShow() { JFrame frame = new JFrame("SLIDE SHOW"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationByPlatform(true); frame.getContentPane().add(this); add(images); frame.setSize(300, 300); frame.setVisible(true); timer = new Timer(2000, action); timer.start(); } public static void main(String... args) { SwingUtilities.invokeLater(new Runnable() { public void run() { new SlideShow(); } }); } } 

Como lo hace con ImageIO, aquí hay un buen ejemplo relacionado con ese JLabel que utiliza ImageIO

Información relacionada con su caso, en cuanto a lo que está sucediendo:

Dentro de su método createAndShowGUI() está inicializando su JLabel (swingImage), y la ha agregado a su JPanel en virtud de lo cual indirectamente al JFrame .

Pero ahora, dentro de su método updateImage() , está inicializando un nuevo JLabel , ahora reside en alguna otra ubicación de memoria, escribiendo tempImage = new JLabel(new ImageIcon(scaledImage)); y después de esto apunta su swingImage(JLabel) para apuntar a este JLabel recién creado, pero este JLabel recién creado nunca se agregó al JPanel , en ningún momento. Por lo tanto, no será visible, incluso si intenta revalidate()/repaint()/setVisible(...) . Por lo tanto, cambie el código de su updateImage(...) a este:

 protected void updateImage(String name) { BufferedImage image = null; Image scaledImage = null; JLabel tempImage; try { image = ImageIO.read(new File(name)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // getScaledImage returns an Image that's been resized // proportionally to my thumbnail constraints scaledImage = getScaledImage(image, THUMB_SIZE_X, THUMB_SIZE_Y); tempImage = new JLabel(new ImageIcon(scaledImage)); rightPane.remove(swingImage); swingImage = tempImage; rightPane.add(swingImage, BorderLayout.PAGE_START); rightPane.revalidate(); rightPane.repaint(); // required sometimes } 

O bien, use JLabel.setIcon(...) como se mencionó anteriormente 🙂

ACTUALIZADO LA RESPUESTA

Aquí vemos cómo se coloca una New JLabel en la posición de la anterior,

 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class SlideShow extends JPanel { private int i = 0; private Timer timer; private JLabel images = new JLabel(); private Icon[] icons = {UIManager.getIcon("OptionPane.informationIcon"), UIManager.getIcon("OptionPane.errorIcon"), UIManager.getIcon("OptionPane.warningIcon")}; private ActionListener action = new ActionListener() { public void actionPerformed(ActionEvent ae) { i++; System.out.println(i); if(i == 4) { timer.stop(); System.exit(0); } remove(images); JLabel temp = new JLabel(icons[i - 1]); images = temp; add(images); revalidate(); repaint(); } }; private void createAndDisplayGUI() { JFrame frame = new JFrame("SLIDE SHOW"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationByPlatform(true); this.setLayout(new FlowLayout(FlowLayout.LEFT)); add(images); frame.getContentPane().add(this, BorderLayout.CENTER); frame.setSize(300, 300); frame.setVisible(true); timer = new Timer(2000, action); timer.start(); } public static void main(String... args) { SwingUtilities.invokeLater(new Runnable() { public void run() { new SlideShow().createAndDisplayGUI(); } }); } } 

Y para su pregunta: ¿ De las dos opciones que he probado, una es mejor que la otra?

setIcon(...) tiene una ventaja en sentido contrario, en el sentido de que no tiene que preocuparse por volver a validar () / repaint () cosa después de agregar / eliminar JLabel . Además, no necesita recordar la ubicación de su JLabel cada vez que lo agrega. Permanece en su posición, y usted simplemente llama al único método para cambiar la imagen, sin condiciones y el trabajo está hecho, sin dolores de cabeza.

Y para la pregunta 2: ¿tenía alguna duda sobre qué es Array of Records ?