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

时间:2015-02-26 10:57:20

标签: java swing loops icons 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++;

2 个答案:

答案 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