for loop issue when cycling through images for Jlabel with button click

霸气de小男生 提交于 2019-12-03 17:53:45

问题


in a java aplication I have a Jlabel which i want to assign a new image to every time i click a button, using a for loop i can get it to just display the last image skipping all in between images, i know there is a error in my logic here maybe i should not be using a for loop?? any advice

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

    }

if i dont use a for loop and simply use a counter (displayed below) which i declare outside of the button method it loops correctly displaying the images but runs into a ArrayIndexOutOfBoundsException. what is the best practice here? thanks

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

回答1:


You're, essentially, blocking the Event Dispatching Thread, prevent it from updating the UI. See Concurrency in Swing for more details

Instead, you should use a javax.swing.Timer to loop over the images, allowing the UI to update before changing to the next one...

See How to use Swing Timers for more details.

Java arrays are zero indexed, this means that the first element in the array is a position 0, not 1

Don't reference src directly within your code, the src directory will not exist once the application is built and packaged

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:


Your counter reaches the end of the array so you get out of bounds exception. After each increment you should check whether the end of array has been reached, and if so, set the counter to 0.

If you want to iterate over a few images with a delay on single click you need to use SwingWorker. Using delays in your action listener will suspend event dispatch thread, which means that no other updates or interactions with swing components will be available (it is likely that refreshes will not be done correctly too).

If you do a few updates (setIcon) in a very short time, Swing usually refreshes the component after the last of them, which means that only last image will be visible.

Have a look here: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html



来源:https://stackoverflow.com/questions/28740572/for-loop-issue-when-cycling-through-images-for-jlabel-with-button-click

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!