krezus
krezus

Reputation: 1451

making slideshow from list of images in java?

I am trying to achieve a slideshow, gif etc. I have listed images read from a folder and make them a sequence for displaying in a SWT dialog. now I have a trouble with thread access. What is the way of making slideshow in SWT. thanks for any advice and correction.

here is the implementation:

    public class ImageShowDialog extends Dialog {

    Shell                    dialog;
    private Label            labelImage;
    private Canvas           canvas;
    int                      numberImage = 0;
    private volatile boolean running     = true;

    ImageShowDialog(Shell parent) {
        super(parent);
    }

    public String open() {
        Shell parent = getParent();
        dialog = new Shell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
        dialog.setSize(600, 400);
        dialog.setText("Show Begins!!!");
        dialog.setLayout(new FillLayout());
        this.func();
        dialog.open();

        Display display = parent.getDisplay();
        while (!dialog.isDisposed()) {
            if (!display.readAndDispatch())
                display.sleep();
        }
        return "After Dialog";
    }

    public void func() {
        final List<byte[]> imageCollection = new ArrayList<byte[]>();

        File path = new File("..\\folder");

        File[] files = path.listFiles();
        for (int i = 0; i < files.length; i++) {
            if (files[i].isFile()) { // this line weeds out other
                // directories/folders
                try {
                    imageCollection.add(loadImage(files[i]));
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (running) {

                    ImageData imageData = new ImageData(
                            new ByteArrayInputStream(
                                    imageCollection.get(numberImage)));
                    final Image image = new Image(Display.getDefault(),
                            imageData);
                    canvas = new Canvas(dialog, SWT.NONE);
                    canvas.addPaintListener(new PaintListener() {
                        public void paintControl(PaintEvent e) {
                            e.gc.setAlpha(255);
                            e.gc.drawImage(image, 0, 0);

                        }
                    });

                    numberImage++;
                    if (numberImage == imageCollection.size())
                        try {
                            running = false;
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

    }

    public byte[] loadImage(File file) throws IOException {

        BufferedImage image = ImageIO.read(file);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ImageIO.write(image, "jpg", bos);
        return bos.toByteArray();
}

and exception:

Exception in thread "Thread-45" org.eclipse.swt.SWTException: Invalid thread access
    at org.eclipse.swt.SWT.error(SWT.java:4282)
    at org.eclipse.swt.SWT.error(SWT.java:4197)
    at org.eclipse.swt.SWT.error(SWT.java:4168)
    at org.eclipse.swt.widgets.Widget.error(Widget.java:468)
    at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:359)
    at org.eclipse.swt.widgets.Widget.checkParent(Widget.java:279)
    at org.eclipse.swt.widgets.Widget.<init>(Widget.java:149)
    at org.eclipse.swt.widgets.Control.<init>(Control.java:110)
    at org.eclipse.swt.widgets.Scrollable.<init>(Scrollable.java:75)
    at org.eclipse.swt.widgets.Composite.<init>(Composite.java:95)
    at org.eclipse.swt.widgets.Canvas.<init>(Canvas.java:79)

Upvotes: 1

Views: 581

Answers (2)

Johan Witters
Johan Witters

Reputation: 1636

SWT is singlethreaded, as described by Riduidel in this post: Updating SWT objects from another thread

So, instead of doing what you do, try the below:

Display.getDefault().asyncExec(new Runnable() {
       public void run() {
ImageData imageData = new ImageData(
                            new ByteArrayInputStream(
                                    imageCollection.get(numberImage)));
                    final Image image = new Image(Display.getDefault(),
                            imageData);
                    canvas = new Canvas(dialog, SWT.NONE);
                    ...
       }
   });

Upvotes: 1

greg-449
greg-449

Reputation: 111142

You can only create and access SWT controls in the main UI thread, any attempt to do so in other threads will give the 'invalid thread access' error you are getting.

You can use the asyncExec or syncExec method of Display in your background thread to run code in the main thread:

Display.getDefault().asyncExec(() ->
   {
     ... code accessing the UI
   });

(Java 8/9 code using a lambda, use a Runnable for old Java).

asyncExec runs the code asynchronously, syncExec waits for the UI thread to run the code before returning.

Upvotes: 1

Related Questions