简体   繁体   中英

Java-Swing : The ImageIcon cannot change in runtime?

I have this code in java

private void buttonShowImageActionPerformed(java.awt.event.ActionEvent evt)
{
    if(folderFiles != null)
    {
        for(int i=0; i<folderFiles.size(); i++)
        {
            icon = new ImageIcon(folderFiles.get(i));
            labelImage.setIcon(icon);
            timeDelay(2);      // A method that delays 2 secs - it works
        }
    }
}

When I push the button, it waits some time, and from the 1st goes to the last image, and skips the images from the folder one-by-one The delay method works (I tested it) Thanks in advance !

Regarding:

timeDelay(2); // A method that delays 2 secs - it works

No, it doesn't work, regardless of how you tested it. Swing doesn't work that way, and you would do well to avoid making such assumptions. Use a Swing Timer.

You will ask, how do I know that it doesn't work, and I'll tell you: that code does not call a background thread, nor does it start a Swing Timer, so the only thing it can do is delay the current thread, likely somewhere with a Thread.sleep(...) . If you call this and "test" this, yes, it will cause delays that will show up in your System.out.println(...) statements to the console, but it will also sleep the Swing event thread, and put your application to sleep. So you really don't want to do this.

And in fact the best test to see if this works in Swing is your current code. What happens then? You state:

When I push the button, it waits some time, and from the 1st goes to the last image, and skips the images from the folder one-by-one

So in fact you know for a fact that your delay doesn't work for Swing, as you describe the classic symptoms of code that stomps on the Swing event thread, bringing it to its knees. So again, use a Swing Timer. Here's a link to the Swing Timer Tutorial .

If this were my code, I'd not read in the images each time the button is pushed, but instead read them all at once, and one time only and put them in an ArrayList<ImageIcon> say called iconList. Assuming that you did this, then the code could look like:

private void buttonShowImageActionPerformed(java.awt.event.ActionEvent evt) {
  // !! I'd use a variable or constant instead of the magic number 2000
  new Timer(2000, new ActionListener() {
    int count = 0;
    actionPerformed(ActionEvent e) {
      if (count != iconList.size()) {
        labelImage.setIcon(iconList.get(count));
        count++;
      } else {
        // stop the Timer
        ((Timer) e.getSource()).stop();
      }
    }
  }).start();
}

Edit
You ask:

My friend one last question ..... I put the "int count = 0;" inside the actionPerformed and nothing happend ... I cannot understand why it works only if it is outside the method .... ?

Please understand that the way a Swing Timer works is that the actionPerformed method is called repeatedly, here every 2000 seconds. What my code does is that when the timer is started, the count is set to 0. Each time the actionPerformed method is called, count increments by 1, and the next ImageIcon is displayed.

With your code, when the actionPerformed method is called, the count is re-set to 0, the first image is displayed, and the count is then incremented. But each time the actionPerformed method is called, your code resets the count back to 0 , so the incrementation has no effect.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM