【问题标题】:making slideshow from list of images in java?从java中的图像列表制作幻灯片?
【发布时间】:2018-06-04 00:19:56
【问题描述】:

我正在尝试制作幻灯片、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


    【解决方案1】:

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

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

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

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

    asyncExec 异步运行代码,syncExec 等待 UI 线程运行代码后再返回。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-10-31
        • 1970-01-01
        • 2017-12-31
        • 2011-08-23
        • 2011-02-07
        • 1970-01-01
        • 2010-11-29
        • 2010-11-24
        相关资源
        最近更新 更多