【问题标题】:How do you draw the Mandelbrot Set in Java using SWING/AWT?如何使用 SWING/AWT 在 Java 中绘制 Mandelbrot 集?
【发布时间】:2019-11-21 01:04:52
【问题描述】:

我正在尝试绘制 Mandelbrot 集合,集合中的点为黑色,其他所有点为白色。在这个初始版本中,我不希望能够放大,而只是创建一个静态图像。

如下所示,我创建了一个 ComplexNumber 类来处理复数的平方和相加。

public class ComplexNumber {

    private double real;
    private double imaginary;

    public ComplexNumber(double real, double imaginary){
        this.real = real;
        this.imaginary = imaginary;
    }

    public ComplexNumber times(ComplexNumber number){

        double a = this.real*number.real;
        double b = this.imaginary*number.real;
        double c = this.real*number.imaginary;
        double d = this.imaginary*number.imaginary*-1;

        double newReal = a+d;
        double newImaginary = b+c;


        ComplexNumber newComplexNumber = new ComplexNumber(newReal, newImaginary);
        return newComplexNumber;
    }

    public ComplexNumber add(ComplexNumber number){

        double newReal = this.real+number.real;
        double newImaginary = this.imaginary+number.imaginary;

        return new ComplexNumber(newReal, newImaginary);

    }

    public double abs(){
        return Math.hypot(this.real, this.imaginary);
    }

    public double getReal() {
        return real;
    }

    public double getImaginary() {
        return imaginary;
    } 
}

这是我渲染 GUI 并实际计算 Mandelbrot 集中点的代码。

    import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;

public class MandelBrotSet extends JComponent {

    public static final int WIDTH = 800;
    public static final int HEIGHT = 800;
    public static final int ITERATIONS = 100;

    public static final double startX = -2;
    public static final double width = 4;
    public static final double startY = 2;
    public static final double height = 4;

    public static final double dx = width/(WIDTH-1);
    public static final double dy = height/(HEIGHT-1);

    private BufferedImage buffer;


    public MandelBrotSet() {

        buffer = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);

        JFrame frame = new JFrame("Mandelbrot Set");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(true);
        frame.getContentPane().add(this);

        frame.pack();
        frame.setVisible(true);


    }

    @Override
    public void addNotify() {
        setPreferredSize(new Dimension(WIDTH, HEIGHT));
    }

    @Override
    public void paint(Graphics g) {
        g.drawImage(buffer, 0, 0, null);
    }

    public void render(){

        for (int x=0; x<WIDTH; x++){
            for (int y=0; y<HEIGHT; y++){
                int color = calculatePoint(x, y);
                buffer.setRGB(x, y, color);
            }
        }
    }



    public int calculatePoint(int x, int y){

        ComplexNumber number = convertToComplex(x, y);
        ComplexNumber z = number;
        int i;
        for (i=0; i<ITERATIONS; i++){

            z = z.times(z).add(number);

            if (z.abs()>2.0){
                break;
            }

        }

        if (i==ITERATIONS) {
            return 0x00000000;
        }
        else {
            return 0xFFFFFFFF;
        }

    }

    public static ComplexNumber convertToComplex(int x, int y){

        double real = startX + x*dx;
        double imaginary = 2 - y*dy;
        return new ComplexNumber(real, imaginary);

    }




    public static void main(String[] args) {

        MandelBrotSet mandy = new MandelBrotSet();
        mandy.render();

    }


}

运行此代码后,我得到了下图。似乎可以瞥见曼德布罗布景,但随后被大量黑色遮住了。我做错了什么?

下面更新了解决方案。感谢您的帮助。

【问题讨论】:

  • AWT/Swing 方法和构造函数只允许从一个特殊线程调用,称为 AWT 事件调度线程。您的 main 方法是它自己的线程;您需要使用EventQueue.invokeLater 在正确的线程中初始化您的 MandelBrotSet 组件。

标签: java swing awt mandelbrot


【解决方案1】:

图像的渲染比显示MandelBrotSet-Object 需要更长的时间,并且之后永远不会更新。 你创建一个MandelBrotSet 类型的对象,然后立即调用它的render 方法。在创建该对象期间,您将其放入您立即显示的JFrame 中。显示框架时,渲染不完整,这就是您的ImageBuffer 尚未填充的原因(构建 mandelbrot-form 需要更长的时间)。

要解决此问题,您可以重新绘制相关组件和框架。我对 awt 的 repaint 函数的理解不足以告诉你如何正确地做到这一点(也许其他人可以在那里提供帮助),但是将它添加到你的渲染方法的末尾应该会有所帮助:

revalidate();
repaint();

revalidate 或 repaint 都可以省略。

如果你用完成的图像更新你的问题会很酷:)

【讨论】:

  • 我在 MandelbrotSet 的构造函数中添加了“render()”,就在“buffer = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);”行之后这样就成功了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-08
  • 2013-01-28
  • 1970-01-01
  • 1970-01-01
  • 2013-03-23
相关资源
最近更新 更多