通过单击按钮循环浏览 Jlabel 的图像时的 for 循环问题
Posted
技术标签:
【中文标题】通过单击按钮循环浏览 Jlabel 的图像时的 for 循环问题【英文标题】:for loop issue when cycling through images for Jlabel with button click 【发布时间】:2016-07-28 16:01:20 【问题描述】:在 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++;
【问题讨论】:
【参考方案1】:本质上,您是在阻止事件调度线程,阻止它更新 UI。更多详情请见Concurrency in Swing
相反,您应该使用 javax.swing.Timer
来循环图像,让 UI 在切换到下一个之前更新...
更多详情请见How to use 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);
【讨论】:
【参考方案2】:您的计数器到达数组的末尾,因此您超出了边界异常。每次递增后,您应检查是否已到达数组末尾,如果已到达,请将计数器设置为 0。
如果您想通过单击延迟迭代一些图像,您需要使用SwingWorker
。在您的动作侦听器中使用延迟将暂停事件调度线程,这意味着没有其他更新或与摆动组件的交互可用(刷新也可能无法正确完成)。
如果您在很短的时间内进行了几次更新 (setIcon
),Swing 通常会在最后一个更新之后刷新组件,这意味着只有最后一个图像可见。
看看这里:http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
【讨论】:
以上是关于通过单击按钮循环浏览 Jlabel 的图像时的 for 循环问题的主要内容,如果未能解决你的问题,请参考以下文章