从java中的图像列表制作幻灯片?

问题描述 投票:1回答:2

我正在尝试实现幻灯片放映,GIF等。我列出了从文件夹中读取的图像,并使它们成为在SWT对话框中显示的序列。现在我遇到线程访问问题。在SWT中制作幻灯片的方式是什么?感谢任何建议和纠正。

这是实施:

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

和例外:

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)
java multithreading swt slideshow
2个回答
1
投票

您只能在主UI线程中创建和访问SWT控件,任何在其他线程中执行此操作的尝试都将导致您获得“无效线程访问”错误。

您可以在后台线程中使用asyncExecsyncExecDisplay方法在主线程中运行代码:

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

(使用lambda的Java 8/9代码,对旧Java使用Runnable)。

asyncExec异步运行代码,syncExec在返回之前等待UI线程运行代码。


1
投票

SWT是单线程的,正如Riduidel在这篇文章中描述的那样:Updating SWT objects from another thread

因此,请尝试以下方法,而不是按照您的方式执行操作:

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);
                    ...
       }
   });
© www.soinside.com 2019 - 2024. All rights reserved.