在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++;
答案 0 :(得分:2)
基本上,您阻止事件调度线程,阻止它更新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);
}
}
}
答案 1 :(得分:1)
您的计数器到达数组的末尾,因此您将超出范围异常。每次递增后,您应检查是否已到达数组的末尾,如果是,则将计数器设置为0。
如果您希望在单击时延迟迭代几张图片,则需要使用SwingWorker
。在动作侦听器中使用延迟将暂停事件派发线程,这意味着没有其他更新或与swing组件的交互可用(很可能刷新也不会正确完成)。
如果你在很短的时间内做了一些更新(setIcon
),Swing通常会在最后一个之后刷新组件,这意味着只有最后一个图像可见。
看看这里:http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html