【问题标题】:BufferedImage does not show after produced by SwingWorkersSwingWorkers 生成的 BufferedImage 不显示
【发布时间】:2012-04-29 02:13:50
【问题描述】:

我正在我的 GUI 中创建一个著名的 Mandelbrot Fractal,为了加快创建图像的速度,我决定使用 Swing Workers。在 doInBackground() 方法中,我正在计算每个像素的颜色,并将所有颜色放入数组中。在 done() 方法中,我正在访问数组并用适当的颜色为每个像素着色。这种方式在 EDT 中完成着色时,在不同的线程中完成大量计算。我只有一个问题 - 没有显示准​​备好的图片,即使我知道它们存储在 BufferedImage 中(我可以将文件保存到我的硬盘驱动器,直接访问 BufferedImage,或者 - 在缩放时 - 我正在创建一个深层副本BufferedImage - 在这种情况下,我可以看到正确的图像)。我对 Java 很陌生,但我希望我的应用程序尽可能好。我的代码在下面和这里:http://pastebin.com/M2iw9rEY

public abstract class UniversalJPanel extends JPanel{

    protected BufferedImage image;
    protected Graphics2D g2d;

    protected int iterations = 100; // max number of iterations
    protected double realMin = -2.0; // default min real
    protected double realMax = 2.0;// default max real
    protected double imaginaryMin = -1.6; // default min imaginary
    protected double imaginaryMax = 1.6;// default max imaginary
    protected int panelHeight;
    protected int panelWidth;
    protected Point pressed, released; // points pressed and released - used to calculate drawn rectangle
    protected boolean dragged; // if is dragged - draw rectangle
    protected int recWidth, recHeight,xStart, yStart; // variables to calculate rectangle
    protected FractalWorker[] arrayOfWorkers; // array of Swing workers



    public abstract int calculateIterations(Complex c);
    public abstract double getDistance(Complex a, Complex b);

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        panelHeight = getHeight();
        panelWidth = getWidth();
        image =new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); // creating new Bufered image
        g2d= (Graphics2D) image.getGraphics();



        arrayOfWorkers= new FractalWorker[getHeight()]; // create new worker for each row and execute them
         for(int q = 0; q < getHeight(); q++ ){
                arrayOfWorkers[q] = new FractalWorker(q);
                arrayOfWorkers[q].execute();
        }

        g.drawImage(image, 0, 0, null); // draw an image

    }   

// *** getters, setters, different code//

private class FractalWorker extends SwingWorker<Object, Object>{
    private int y;  // row on which worker should work now
    private Color[] arrayOfColors; // array of colors produced by workers
    public FractalWorker( int z){
        y = z;      
    }
    protected Object doInBackground() throws Exception {

        arrayOfColors = new Color[getWidth()];

        for(int q=0; q<getWidth(); q++){ // calculate and insert into array proper color for given pixel
            int iter = calculateIterations(setComplexNumber(new Point(q,y))); 
            if(iter == iterations){
                arrayOfColors[q] = Color.black;
            }else{
                arrayOfColors[q] = Color.getHSBColor((float)((iter/ 20.0)), 1.0f, 1.0f );
            }
        }           
        return null;
    }
    protected void done(){ // take color from the array and draw pixel
        for(int i = 0; i<arrayOfColors.length; i++){            
            g2d.setColor(arrayOfColors[i]);
            g2d.drawLine(i, y, i, y);
        }
    }

}

【问题讨论】:

    标签: bufferedimage swingworker


    【解决方案1】:

    当您调用 g.drawImage(...) 时,图像的当前内容被绘制到组件中。那时 SwingWorkers 还没有完成他们的工作,因为您在 drawImage 调用之前立即启动它们。你不应该在paintComponent方法中启动SwingWorkers,如果已经收到了一个绘制请求,那么开始一个漫长的绘制过程已经太迟了。

    更好的解决方案可能是在程序启动时创建 BufferedImage,然后在组件大小发生变化时重新创建它。然后,您应该在需要重绘时启动 SwingWorker,并在它们完成绘图后调用组件上的 repaint()。

    【讨论】:

    • 如何检查 SwingWorkers 是否已完成执行 done() 方法中的内容?而且我不确定当我启动程序时创建 BufferedImage 是什么意思 - 我认为通过调用方法 paintComponent() 我正在这样做。 “ (...) 然后在组件大小发生变化时重新创建它。” - 我根本没有改变我的组件的大小。感谢您的帮助。
    • 您的程序不应该直接调用paintComponent 方法——Swing 会这样做。您的程序必须能够快速响应任何paintComponent 调用。这就是为什么您必须在paintComponent 启动之前准备好并绘制图像的原因。如果图像内容发生变化,则需要调用 panel.repaint() 重新绘制组件,这会导致 Swing 调用paintComponent。要确定您的 SwingWorkers 是否已完成,您可以在 done() 末尾设置一个布尔值,然后保留所有工作人员的列表并对其进行迭代检查布尔值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-14
    • 2011-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多