通过按钮单击循环浏览Jlabel的图像时出现循环问题

在java应用程序中我有一个Jlabel,我想在每次单击一个按钮时分配一个新图像,使用for循环我可以让它只显示跳过图像之间的所有最后一个图像,我知道有一个错误在我的逻辑中,也许我不应该使用for循环? 任何建议

private String imageList[]; ImageIcon image; imageList = new String[] {"src\\Tour_Eiffel_Wikimedia_Commons.jpg","src\\Ben.jpg", "src\\Rio.jpg", "src\\Liberty.jpg", "src\\Pyramid.jpg"}; //constructor setting first image to display on load public GeographyGameGUI() { image = new ImageIcon(imageList[0]); imageLbl.setIcon(image); } //button method private void nextBtnActionPerformed(java.awt.event.ActionEvent evt) { for (imgCount = 1; imgCount < imageList.length; imgCount++) { image = new ImageIcon(imageList[imgCount]); imageLbl.setIcon(image); } 

如果我不使用for循环并简单地使用我在按钮方法之外声明的计数器(如下所示),它会正确地循环显示图像但会遇到ArrayIndexOutOfBoundsException。 这里最好的做法是什么? 谢谢

  image = new ImageIcon(imageList[imgCount]); imageLbl.setIcon(image); imgCount++; 

实质上,您阻止了事件调度线程,阻止它更新UI。 有关更多详细信息,请参阅Swing中的并发

相反,您应该使用javax.swing.Timer来循环图像,允许UI在更改为下一个之前更新…

有关更多详细信息,请参见如何使用Swing Timers 。

Java数组是零索引的,这意味着数组中的第一个元素是位置0 ,而不是1

不要直接在代码中引用src ,一旦构建和打包应用程序, src目录就不会存在

 import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.Timer; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class Test { public static void main(String[] args) { new Test(); } public Test() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class TestPane extends JPanel { private JLabel label; private String[] imageList = new String[] {"/Tour_Eiffel_Wikimedia_Commons.jpg","/Ben.jpg", "/Rio.jpg", "/Liberty.jpg", "/Pyramid.jpg"}; public TestPane() { setLayout(new BorderLayout()); label = new JLabel(); add(label); JButton btn = new JButton("Play"); btn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { btn.setEnabled(false); Timer timer = new Timer(1000, new ActionListener() { private int count; @Override public void actionPerformed(ActionEvent e) { if (count < imageList.length) { try { label.setIcon( new ImageIcon( ImageIO.read( TestPane.this.getClass().getResource(imageList[count])))); } catch (IOException exp) { exp.printStackTrace(); } count++; } else { ((Timer)e.getSource()).stop(); } } }); timer.stop(); } }); } @Override public Dimension getPreferredSize() { return new Dimension(200, 200); } } } 

您的计数器到达数组的末尾,因此您将超出范围exception。 每次增加后,应检查是否已到达数组的末尾,如果是,则将计数器设置为0。

如果要在单击时延迟迭代几张图像,则需要使用SwingWorker 。 在动作侦听器中使用延迟将暂停事件分派线程,这意味着没有其他更新或与swing组件的交互可用(很可能刷新也不会正确完成)。

如果你在很短的时间内做了一些更新( setIcon ),Swing通常会在最后一个之后刷新组件,这意味着只有最后一个图像可见。

看看这里: http : //docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html