问题
This is the part of the code where i have a problem. I should display each picture every after 5 seconds but it doesn't work. I hope you can help. Thanks
EDIT: All pictures are displayed together after 5 seconds
JButton btnGenerateNumber = new JButton("Generate Number");
btnGenerateNumber.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent arg0) {
ImageIcon apple = new ImageIcon("Resources/apple.png");
try{
for(int i=0; i<labelApp.length; i++){
remove(labelApp[i]);
}
}catch(Exception e){
}
Random rand = new Random();
int number = rand.nextInt(10)+1;
labelApp = new JLabel[number];
for(i=0; i<number; i++){
labelApp[i] = new JLabel(apple);
labelApp[i].setBounds(500, 100 + 10 * i, 40, 39);
add(labelApp[i]);
Timer t = new Timer(5000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
revalidate();
repaint();
}
});
t.start();
}
labelNum.setText(number + " ");
}
});
回答1:
Your problem is that with your for loop you create images all at once, create labels all at once, and create a bunch of Swing Timers that don't do anything useful. You shouldn't use a for loop to go through your images, that instead create a single JLabel and most importantly a single Swing Timer, and the timer will substitute for the for-loop. Instead of a loop, the Timer's actionPerformed method will be repeatedly called.
Suggestions:
- Don't try to use a for loop to swap images -- that's the console way of doing this, and won't work for Swing GUI's.
- Create a single image viewer JLabel to view the images, and leave it on the GUI. Don't add and remove it, and don't create a new JLabel for each image.
- Read all the images in at one time, perhaps in a constructor (if the images are not too big).
- Convert the images into ImageIcons and save them in an
ArrayList<Icon>. - In your Swing Timer, do much more than
repaint()andrevalidate(). Instead advance an index to the ArrayList, make sure that it's not equal to or greater than the list's size, and get the image from the list and place it in the image viewer JLabel. - Done.
For example:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.*;
public class SwapImages extends JPanel {
private static final int TIMER_DELAY = 200;
private static final String SPRITE_PATH = "http://th02.deviantart.net/"
+ "fs70/PRE/i/2011/169/0/8/blue_player_sprite_sheet_by_resetado-d3j7zba.png";
public static final int SPRITE_ROWS = 6;
public static final int SPRITE_COLS = 6;
public static final int SPRITE_CELLS = 35;
private JLabel label = new JLabel();
private List<Icon> iconList = new ArrayList<>();
private int iconIndex = 0;
public SwapImages() throws IOException {
URL imgUrl = new URL(SPRITE_PATH);
BufferedImage mainImage = ImageIO.read(imgUrl);
for (int i = 0; i < SPRITE_CELLS; i++) {
int row = i / SPRITE_COLS;
int col = i % SPRITE_COLS;
int x = (int) (((double) mainImage.getWidth() * col) / SPRITE_COLS);
int y = (int) ((double) (mainImage.getHeight() * row) / SPRITE_ROWS);
int w = (int) ((double) mainImage.getWidth() / SPRITE_COLS);
int h = (int) ((double) mainImage.getHeight() / SPRITE_ROWS);
BufferedImage img = mainImage.getSubimage(x, y, w, h);
ImageIcon icon = new ImageIcon(img);
iconList.add(icon);
}
add(label);
label.setIcon(iconList.get(iconIndex));
new Timer(TIMER_DELAY, new TimerListener()).start();
}
private class TimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent arg0) {
iconIndex++;
iconIndex %= iconList.size();
label.setIcon(iconList.get(iconIndex));
}
}
private static void createAndShowGui() {
SwapImages mainPanel = null;
try {
mainPanel = new SwapImages();
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
JFrame frame = new JFrame("SwapImages");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
The key to the code above is the Timer's ActionListener:
private class TimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent arg0) {
iconIndex++;
iconIndex %= iconList.size();
label.setIcon(iconList.get(iconIndex));
}
}
What it does is increment an int variable that acts as the index to the ArrayList that holds the images (ImageIcons actually). So first I increment the index, then I change it to 0 if it matches the size of the iconList ArrayList, then I get the icon and set it into the JLabel. Simple.
回答2:
The problem is that in your for loop you set the timer to 5 Secs. The for loop will be very fast, like completed in a few milliseconds. You kick off the timers within a few milliseconds, so they are finished at the same time (5 secs +a few millis).
Even though this is not a good way to do it, your problem would be solved if you trigger the first timer after 5 secs, the second after 10 and so forth (said again, this is not very well coded).
来源:https://stackoverflow.com/questions/35972152/how-to-display-pictures-on-jpanel-with-delay