Java slide image delay using paintComponent

I am compiling a slide show program that will measure the user’s time spent on each slide. The slide show runs through several different tricks. Each trick is shown twice. Intermediate images are shown between repetitions. Transitional images are displayed between each trick.

When the trick is repeated for the first time after the next image is shown, the JPanel color will blink. This does not happen during the second repetition of the same trick. The image may be loading too long.

Is there an easy way to preload images so that there is no delay for the first time?

NOTE: Original code deleted. 

EDIT 1/10/2013: This code now works on slower machines. The second trashgod application helped the best. The mouseClick control structure periodically requests SwingWorker classes to load 40 images or less of the current trick, and also to set the images used to zero. I simplified my code for this with only two Image [] s and added the main method, so it costs one. Images are still needed to run. Now this is a pretty simple bone code, and if you are trying to make a slideshow with a lot of images, I think this will be a good place to start.

NOTE. I think I figured out how to implement SwingWorker correctly while still using multiple Image [] s. trashgod and kleopatra is the implementation according to what you suggested? I did not finish using the publication and the process, since I could not figure out how to make it work properly with the indexed array, but since StringWorker does not load all the images in the array (40 in total), and the code calls StringWorker every 20 images, it should be pretty good buffer.

EDIT 1/10/2013 Changed MouseListener, instead extending MouseAdapter to my Mouse class. My paintComponent method has also been fixed to enable the call to super.paintComponent (g). Added publishing / process methods for my SwingWorker ImageWorker class. An ArrayWrapper wrapper class has been added that allows you to pass imageArray [i] and its corresponding int index i with publication for processing.

 package slideshow3; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseAdapter; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import java.util.List; public class SlideShow3 extends JFrame { //screenImage will be replaced with each new slide private Image screenImage; private int width; private int height; //Create panel for displaying images using paintComponent() private SlideShow3.PaintPanel mainImagePanel; //Used for keybinding private Action escapeAction; //Image array variables for each trick private Image[] handCuffs; //h private Image[] cups; //c //Used to step through the trick arrays one image at a time private int h = 0; private int c = 0; //Used by timeStamp() for documenting time per slide private long time0 = 0; private long time1; public SlideShow3() { super(); //Create instance of each Image array handCuffs = new Image[50]; cups = new Image[176]; //start(handCuffsString); start("handCuffs"); try { screenImage = ImageIO.read(new File("images/begin1.jpg")); } catch (IOException nm) { System.out.println("begin"); System.out.println(nm.getMessage()); System.exit(0); } /****************************************** * Removes window framing. The next line sets fullscreen mode. * Once fullscreen is set width and height are determined for the window ******************************************/ this.setUndecorated(true); GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(this); width = this.getWidth(); height = this.getHeight(); //Mouse click binding to slide advance control structure addMouseListener(new Mouse()); //Create panel so that I can use key binding which requires JComponent mainImagePanel = new PaintPanel(); add(mainImagePanel); /****************************************** * Key Binding * ESC will exit the slideshow ******************************************/ // Key bound AbstractAction items escapeAction = new EscapeAction(); // Gets the mainImagePanel InputMap and pairs the key to the action mainImagePanel.getInputMap().put(KeyStroke.getKeyStroke("ESCAPE"), "doEscapeAction"); // This line pairs the AbstractAction enterAction to the action "doEnterAction" mainImagePanel.getActionMap().put("doEscapeAction", escapeAction); /****************************************** * End Key Binding ******************************************/ } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { SlideShow3 show = new SlideShow3(); show.setVisible(true); } }); } //This method executes a specific SwingWorker class to preload images public void start(String e) { if(e.equals("handCuffs")) { new ImageWorker(handCuffs.length, h, e).execute(); } else if(e.equals("cups")) { new ImageWorker(cups.length, c, e).execute(); } } //Stretches and displays images in fullscreen window private class PaintPanel extends JPanel { @Override public void paintComponent(Graphics g) { if(screenImage != null) { super.paintComponent(g); g.drawImage(screenImage, 0, 0, width, height, this); } } } /****************************************** * The following SwingWorker class Pre-loads all necessary images. ******************************************/ private class ArrayWrapper { private int i; private Image image; public ArrayWrapper(Image image, int i) { this.i = i; this.image = image; } public int getIndex() { return i; } public Image getImage() { return image; } } private class ImageWorker extends SwingWorker<Image[], ArrayWrapper> { private int currentPosition; private int arraySize; private String trickName; private Image[] imageArray; public ImageWorker(int arraySize, int currentPosition, String trick) { super(); this.currentPosition = currentPosition; this.arraySize = arraySize; this.trickName = trick; } @Override public Image[] doInBackground() { imageArray = new Image[arraySize]; for(int i = currentPosition; i < currentPosition+40 && i < arraySize; i++) { try { imageArray[i] = ImageIO.read(new File("images/" + trickName + (i+1) + ".jpg")); ArrayWrapper wrapArray = new ArrayWrapper(imageArray[i], i); publish(wrapArray); } catch (IOException e) { System.out.println(trickName); System.out.println(e.getMessage()); System.exit(0); } } return imageArray; } @Override public void process(List<ArrayWrapper> chunks) { for(ArrayWrapper element: chunks) { if(trickName.equals("handCuffs")) { handCuffs[element.getIndex()] = element.getImage(); } else if(trickName.equals("cups")) { cups[element.getIndex()] = element.getImage(); } } } @Override public void done() { try { if(trickName.equals("handCuffs")) { handCuffs = get(); } else if(trickName.equals("cups")) { cups = get(); } } catch(InterruptedException ignore){} catch(java.util.concurrent.ExecutionException e) { String why = null; Throwable cause = e.getCause(); if(cause != null) { why = cause.getMessage(); } else { why = e.getMessage(); } System.err.println("Error retrieving file: " + why); } } } /****************************************** * End SwingWorker Pre-Loading Classes ******************************************/ //Prints out time spent on each slide public void timeStamp() { time1 = System.currentTimeMillis(); if(time0 != 0) { System.out.println(time1 - time0); } time0 = System.currentTimeMillis(); } /****************************************** * User Input Classes for Key Binding Actions and Mouse Click Actions ******************************************/ private class EscapeAction extends AbstractAction { @Override public void actionPerformed(ActionEvent e) { System.exit(0); } } public class Mouse extends MouseAdapter { @Override public void mouseClicked(MouseEvent e) { if(!(h<handCuffs.length) && !(c<cups.length)) { timeStamp(); System.exit(0); } else if(h<handCuffs.length) { timeStamp(); screenImage = handCuffs[h]; repaint(); System.out.print("handCuffs[" + (h+1) + "]\t"); h++; //purge used slides and refresh slide buffer if(h == 20 || h == 40) { for(int i = 0; i < h; i++) { handCuffs[i] = null; } start("handCuffs"); } if(h == 45) { start("cups"); } } else if(c<cups.length) { timeStamp(); screenImage = cups[c]; repaint(); System.out.print("cups[" + (c+1) + "]\t"); c++; //purge used slides and refresh slide buffer if(c == 20 || c == 40 || c == 60 || c == 80 || c == 100 || c == 120 || c == 140 || c == 160) { for(int i = 0; i < c; i++) { cups[i] = null; } start("cups"); } } } } /****************************************** * End User Input Classes for Key Binding Actions and Mouse Click Actions ******************************************/ } 
+4
source share
1 answer

This example uses List<ImageIcon> as a cache images returned by getImage() . Using getResource() , the delay is invisible. The next and previous buttons are tied to the default Space button.

Application: you can control navigation by creating the state of the setEnabled() button using an instance of javax.swing.Timer , for example .

Appendix: your second example waits until the mouse is clicked to start reading the image, an undefined process that can immediately return a copy or not complete until repaint() . Instead, start reading images in the background using ImageIO.read() , as shown here . You can process() your List<Image> and show the progress as shown here . SwingWorker can be started from the initial thread , working while you subsequently create your GUI on EDT. You can display the first image immediately after processing it.

+5
source

All Articles