更新包含在JLabel中的图像 – 问题

我目前遇到麻烦的应用程序的一部分是能够滚动并显示一个图像列表,一次一个。 我从用户那里得到一个目录,并在那个目录下的所有文件中进行后台处理,然后加载一个只包含jpeg和png的数组。 接下来,我想用第一个图像更新JLabel,并提供上一个和下一个button,依次滚动显示每个图像。 当我试图显示第二个图像,它不会得到更新…这是我迄今为止:

public class CreateGallery { private JLabel swingImage; 

我用来更新图像的方法:

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

然后在我的createAndShowGUI方法,把swingImage …

 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 + "http://img.dovov.comdefault.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(); } }); } 

如果你已经得到这么多,第一个图像是我的default.jpg,一旦我得到的目录,并确定该目录中的第一个图像,这是我尝试更新swingImage失败的地方。 现在,我试图swingImage.setVisible()和swingImage.revalidate()来试图强制它重新加载。 我猜这是我的tempImage =新的JLabel,这是根本原因。 但我不知道如何将我的BufferedImage或图像转换为JLabel以更新swingImage。

不用为每个Image创build一个JLabelNew Instance ,只需使用JLabel的JLabel#setIcon(…)方法来更改图像。

一个小样本程序:

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

既然你用ImageIO来做这个,那么这个例子就是和使用ImageIO的JLabel相关的

有关您的案例的信息,关于正在发生的事情:

在你的createAndShowGUI()方法里面初始化你的JLabel (swingImage),并且通过间接的方式把它添加到你的JPanel

但是现在在你的updateImage()方法中,通过写入tempImage = new JLabel(new ImageIcon(scaledImage)); ,你正在初始化一个新的JLabel ,现在它驻留在另一个内存位置tempImage = new JLabel(new ImageIcon(scaledImage)); 在此之后,你指定你的swingImage(JLabel)指向这个新创build的JLabel ,但是这个新创build的JLabel从来没有被添加到JPanel 。 因此,即使你尝试了revalidate()/repaint()/setVisible(...) ,它也是不可见的。 因此要么你更改你的updateImage(...)方法的代码为:

 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 } 

或者如前所述使用JLabel.setIcon(...) 🙂

更新了答案

在这里,看看一个New JLabel如何被放置在旧的位置,

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

而对于你的问题: 在我试过的两个选项中,哪一个比另一个好?

setIcon(...)在另一个方面有一个优势, setIcon(...) ,在添加/删除JLabel之后,你不必担心revalidate()/ repaint()的问题。 而且,您不需要每次都记住JLabel的位置,您可以添加它。 它仍然在它的位置,你只需要调用一个方法来改变图像,没有任何附加的string和工作完成,没有任何头痛。

而对于问题2:我有点怀疑,至于什么是Array of Records