1

GUI でよく知られているマンデルブロー フラクタルを作成しています。イメージの作成を高速化するために、Swing Workers を使用することにしました。メソッド doInBackground() では、すべてのピクセルの色を計算し、すべての色を配列に入れています。メソッド done() では、配列にアクセスし、各ピクセルに適切な色を付けています。このように、重い計算は異なるスレッドで実行され、カラーリングは EDT で実行されます。問題が1つだけあります.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);
        }
    }

}
4

1 に答える 1

0

g.drawImage(...)を呼び出すと、画像の現在のコンテンツがコンポーネントに描画されます。その時点で、drawImage呼び出しの直前に開始したため、SwingWorkersは作業を完了していません。paintComponentメソッドでSwingWorkersを開始しないでください。ペイント要求を受信した場合、長い描画プロセスを開始するには遅すぎます。

より良い解決策は、プログラムの起動時にBufferedImageを作成し、コンポーネントのサイズが変更されたときにそれを再作成することです。次に、再描画が必要な場合は常にSwingWorkersを起動し、描画が終了したらコンポーネントでrepaint()を呼び出す必要があります。

于 2012-04-17T18:01:18.653 に答える