SWT gc.setAdvanced(true)导致阻塞状态

时间:2013-03-09 17:25:48

标签: image swt

我有一些繁重的系统资源图像处理(需要将图像放大得很深)并将缩放图像的一部分(让我们称之为视口)绘制到画布上。

因为调整到如此巨大尺寸的图像会导致阻塞UI几秒钟,所以我制作了背景线程来调整图像大小,当图像准备就绪时,它会被使用。在此之前,使用了paintevent gc和SWT transformations(它们很快,但比已经调整大小的图像的视口操作慢了大约10倍)。

但在我写完大小调整线程后,它仍会阻止UI。所以我让SSCCE证明了这一点。不幸的是,它完美无缺。经过几个小时的调试后,我发现gc.setAdvanced(true);导致GC上下文阻塞。

import java.net.URL;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class ImageResizeTest {
    private Image bgImage;
    private Image imgToResize;
    private ImageResizeWorker worker;
    private Display display = new Display();
    private Shell shell = new Shell(display);

    public ImageResizeTest() {
        shell.setText("Image background resize test");

        Rectangle rect = new Rectangle(0, 0, 500, 500);
        bgImage = new Image(display, rect);
        paintImage(bgImage);

        shell.addPaintListener(new PaintListener() {
            @Override
            public void paintControl(PaintEvent e) {
                System.out.println("redraw start");
                e.gc.drawImage(bgImage, 0, 0);
                e.gc.setAdvanced(true);
                e.gc.fillRectangle(new Rectangle((int)(Math.random() * 100), (int)(Math.random() * 100), 20, 20));
                System.out.println("redraw stop");
            }
        });

        shell.addKeyListener(new KeyAdapter() {

            /* (non-Javadoc)
             * @see org.eclipse.swt.events.KeyAdapter#keyPressed(org.eclipse.swt.events.KeyEvent)
             */
            @Override
            public void keyPressed(KeyEvent e) { 
                worker = new ImageResizeWorker(new Image(display, imgToResize, SWT.IMAGE_COPY));
                worker.start();
                display.asyncExec(new Runnable() {
                    @Override
                    public void run() {
                        shell.redraw();
                        try {
                            Thread.sleep(250);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        if (worker.isAlive()) display.asyncExec(this);
                    }
                });
            }
        });

        try {
            URL url = new URL("http://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Image_created_with_a_mobile_phone.png/1280px-Image_created_with_a_mobile_phone.png");
            imgToResize = new Image(display, url.openStream());
            paintImage(imgToResize);
        } catch (Exception e) {
            e.printStackTrace();
        }

        shell.setActive();
        shell.setBounds(rect);
        shell.setVisible(true);

        while(!shell.isDisposed()) {
            if(!display.readAndDispatch()) display.sleep();
        }

        shell.dispose();
    }

    private void paintImage(Image img) {
        Rectangle rect = img.getBounds();
        GC gc = new GC(img);
        for (int i = 0; i < 20; i++) {
            gc.drawLine((int)(Math.random() * rect.width), (int)(Math.random() * rect.height), (int)(Math.random() * rect.width), (int)(Math.random() * rect.height));
        }
        gc.dispose();
    }

    private class ImageResizeWorker extends Thread {
        private Image srcImage;

        public ImageResizeWorker(Image srcImage) {
            this.srcImage = srcImage;
        }

        /* (non-Javadoc)
         * @see java.lang.Thread#run()
         */
        @Override
        public void run() {
            System.out.println("resizing started");
        Image targetImage = new Image(new Display(), 31000, 15000);
        long time = System.currentTimeMillis();
        GC gc = new GC(targetImage);
        gc.setAdvanced(true);
        gc.setInterpolation(SWT.HIGH);
        gc.drawImage(srcImage, 0, 0, srcImage.getBounds().width, srcImage.getBounds().height, 0, 0, 31000, 15000);
        System.out.println("Took " + (System.currentTimeMillis() - time) + " ms");
        gc.dispose();
        bgImage = targetImage;
        }
    }

    public static void main(String[] args) {
        new ImageResizeTest();
    }
}

如果两个gc.setAdvanced(true);都被注释掉,它就会正常工作。

有人可以告诉我导致阻止的原因以及如何避免阻塞吗?是的,我需要在高级模式下同时拥有两个线程(mainworker) ,因为我需要在main中使用抗锯齿进行线条绘制,并在gc.setInterpolation(SWT.HIGH);中使用worker以在调整大小后使用合理的图像质量。

0 个答案:

没有答案