Ändern Sie den Inhalt von BufferedImage und aktualisieren Sie dann JFrame, um ihn wiederzugeben

Ich versuche, einen Mandelbrot-Set-Renderer mit einer GUI zu erstellen, in der Sie klicken und ziehen können, um in einen bestimmten Bereich zu zoomen. Beim Ausführen werden die anfänglichen Berechnungen und das Rendern ausgeführt. Wenn Sie jedoch zum Vergrößern klicken und ziehen, werden die Berechnungen in der Konsole angezeigt, der Inhalt von JFrame wird jedoch nicht aktualisiert.

Ich bin mir jedoch nicht sicher, dass es sich um eine Neuberechnung handelt, da die anfängliche Berechnung etwa 8 Sekunden dauert, aber wenn Sie zum Zoomen klicken / ziehen, dauert es etwa 6 ms.

Ich habe meinen Code unten gepostet.

Complex Numbers Class

public class Complex {
    private double real, imag;

    // Constructors
    public Complex(){
        real=0.0;
        imag=0.0;
    }

    public Complex(double real, double imag) {
        this.real=real;
        this.imag=imag;
    }

    // add given complex number to this one, returning the Complex result
    public Complex add(Complex other) {
        return new Complex(this.real+other.real, this.imag+other.imag);
    }

    // multiply given complex number by this one, returning the Complex result
    public Complex multiply(Complex other) {
        return new Complex((this.real*other.real)-(this.imag*other.imag), (this.imag*other.real)+(this.real*other.imag));
    }

    // get the magnitude of this complex number
    public double getMagnitude() {
        return Math.sqrt((real*real)+(imag*imag));
    }
}

Runnable MandelbrotTask Class

public class MandelbrotTask implements Runnable {
    private double x1, y1, x2, y2;
    private int startCol, endCol, startRow, endRow, maxIters;
    private int[][] iterCounts;

       public MandelbrotTask(int maxIters, double x1, double y1, double x2, double y2, int startCol, int endCol, int startRow, int endRow, int[][] iterCounts) {
            this.x1 = x1;
            this.y1 = y1;
            this.x2 = x2;
            this.y2 = y2;
            this.startCol = startCol;
            this.endCol = endCol;
            this.startRow = startRow;
            this.endRow = endRow;
            this.iterCounts = iterCounts;
            this.maxIters=maxIters;         
}

    @Override
    public void run() {
        for (int i = startRow; i < endRow; i++) {
            for (int j = startCol; j < endCol; j++) {
                Complex c = getComplex(i, j);
                int iterCount = countIters(c);
                iterCounts[i][j] = iterCount;
            }
        }
    }

    public Complex getComplex(int i, int j){
        //output image is 600 X 600 pixels
        double incrementX;
        double incrementY;
        if(x2!=x1){
            incrementX=(Math.abs(x2-x1)/600);
        }
        else{
            throw new ArithmeticException("Error: area=0");
        }
        if(y2!=y1){
            incrementY=(Math.abs(y2-y1)/600);
        }
        else{
            throw new ArithmeticException("Error: area=0");
        }

        return new Complex(x1+((double)i*incrementX), y1+((double)j*incrementY));
    }

    public int countIters(Complex c){
        Complex z=new Complex(0, 0);
        int iters=0;
        while(z.getMagnitude()<2 && iters<=maxIters){
            z=z.multiply(z).add(c);
            iters++;
        }
        return iters;
    }
}

Main Mandelbrot Class

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Scanner;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class Mandelbrot {
    private static final int HEIGHT = 600;
    private static final int WIDTH = 600;
    private static final int maxIters=50000;

    private static Rectangle zoomBox;
    private static Point initialClick;
    private static JLabel content; //bufferedImage will be put into this JLabel
    private static int[][] iterCounts;
    private static BufferedImage bufferedImage; //rendering will be written to this bufferedImage
    private static JFrame frame;

    public static void main(String[] args) throws IOException {
        zoomBox=null;
        Scanner keyboard = new Scanner(System.in);

        double x1 = -2;
        double y1 = -2;
        double x2 = 2;
        double y2 = 2;
        /*System.out.print("Max iterations (16,581,375 supported): ");
        int maxIters=50000;
        if(maxIters>16581375){
            throw new UnsupportedOperationException("Error: Max Iterations: Overflow.");
        }
        System.out.print("Output filename: ");
        String fileName = keyboard.next();
        if(!fileName.endsWith(".png") && !fileName.endsWith(".PNG")){
            fileName=fileName + ".png";
        }*/

        // TODO: create the rendering, save it to a file
        iterCounts=new int[WIDTH][HEIGHT];
        recalculate(x1, y1, x2, y2, iterCounts);

        bufferedImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
        MouseAdapter listener = new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                handleMousePressed(e);
            }

            @Override
            public void mouseDragged(MouseEvent e) {
                handleMouseDragged(e);
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                handleMouseReleased(e);
            }
        };
        content=new JLabel(new ImageIcon(render(iterCounts, bufferedImage, zoomBox, true)));
        content.addMouseListener(listener);
        content.addMouseMotionListener(listener);

        /*OutputStream os = new BufferedOutputStream(new FileOutputStream(fileName));
        try {
            ImageIO.write(bufferedImage, "PNG", os);
        } finally {
            os.close();
        }*/


        frame = new JFrame("Mandelbrot Viewer");
        frame.getContentPane().add(content);
        frame.pack();
        frame.setSize(new Dimension(WIDTH, HEIGHT));
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    public static BufferedImage render(int[][] iterCounts, BufferedImage bufferedImage, Rectangle zoomBox, boolean updated){
        bufferedImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
        Graphics g = bufferedImage.getGraphics();
        Graphics2D g2=(Graphics2D) g;
        if(updated){
            for(int i=0; i<WIDTH; i++){
                for(int j=0; j<HEIGHT; j++){
                    if(iterCounts[i][j]<maxIters){
                        String hexCode= String.format("#%06x", (0xFFFFFF & (32*iterCounts[i][j])));
                        g.setColor(Color.decode(hexCode));
                    }
                    else{
                        g.setColor(Color.CYAN);
                    }
                    g.drawLine(i, j, i, j);
                }
            }
        }
        else{
            if(zoomBox!=null){
                g2.setStroke(new BasicStroke(7));
                g2.draw(zoomBox);
            }
        }

        return bufferedImage;
    }

    public static int[][] recalculate(double x1, double y1, double x2, double y2, int[][] iterCounts){
        MandelbrotTask[] tasks=new MandelbrotTask[4];
        tasks[0]=new MandelbrotTask(maxIters, x1, y1, x2, y2, 0, WIDTH, 0, HEIGHT/4, iterCounts);
        tasks[1]=new MandelbrotTask(maxIters, x1, y1, x2, y2, 0, WIDTH, HEIGHT/4, 2*(HEIGHT/4), iterCounts);
        tasks[2]=new MandelbrotTask(maxIters, x1, y1, x2, y2, 0, WIDTH, 2*(HEIGHT/4), 3*(HEIGHT/4), iterCounts);
        tasks[3]=new MandelbrotTask(maxIters, x1, y1, x2, y2, 0, WIDTH, 3*(HEIGHT/4), 4*(HEIGHT/4), iterCounts);
        //parallelize computation
        Thread[] threads=new Thread[4];
        for(int i=0; i<4; i++){
            threads[i]=new Thread(tasks[i]);
        }

        System.out.println("Working...");
        //start timer, start computation
        long start=System.currentTimeMillis();
        for(int i=0; i<4; i++){
            threads[i].start();
        }

        for(int i=0; i<4; i++){
            try {
                threads[i].join();
            } catch (InterruptedException e) {
                System.err.println("A thread was interrupted.");
            }
        }
        //end timer
        long end=System.currentTimeMillis();
        long elapsed=end-start;
        System.out.println("Done.");
        System.out.println("Took " + elapsed + " ms.");

        return iterCounts;
    }

    protected static void handleMousePressed(MouseEvent e) {
        initialClick=e.getPoint();
    }

    protected static void handleMouseDragged(MouseEvent e) {
        if(e.getX()>e.getY()){
            zoomBox=new Rectangle((int)initialClick.getX(), (int)initialClick.getY(), (int)(e.getX()-initialClick.getX()), (int)(e.getY()-initialClick.getX()));
        }
        else if(e.getY()>e.getX()){
            zoomBox=new Rectangle((int)initialClick.getX(), (int)initialClick.getY(), (int)(e.getX()-initialClick.getY()), (int)(e.getY()-initialClick.getY()));
        }
        else{
            zoomBox=new Rectangle((int)initialClick.getX(), (int)initialClick.getY(), (int)(e.getX()-initialClick.getX()), (int)(e.getY()-initialClick.getY()));
        }
        content=new JLabel(new ImageIcon(render(iterCounts, bufferedImage, zoomBox, false)));
        content.repaint();
    }

    protected static void handleMouseReleased(MouseEvent e) {
        recalculate(initialClick.getX(), initialClick.getY(), e.getX(), e.getY(), iterCounts);
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                zoomBox=null;
                content=new JLabel(new ImageIcon(render(iterCounts, bufferedImage, zoomBox, false)));
                content.repaint();
            }
        });
    }
}