更改变量时重绘不起作用

时间:2019-08-22 16:35:16

标签: java repaint

我对使用Java开发非常陌生,但是我有一些通用的编码经验。我知道想用我创建的功能绘制“图片/分形”。我完成了所有代码,我想通过仅向函数XOFF添加(我有一个计时器)来自动移动“分形”,现在我希望变量自动增加以使其在图片中滚动。我尝试使用重新绘制和重新验证,但是它不起作用:(

我知道我写了MandelBrotSet,尽管它与它没有任何关系^^

package Pack1;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;

import javax.swing.Timer;
import javax.swing.JComponent;
import javax.swing.JFrame;

public class Main extends JComponent implements ActionListener {
    public static void main(String[] args) {
        new Main();
    }

    public static final int WIDTH = 1000;
    public static final int HEIGHT = 800;
    public int XOFF = 0;
    public int YOFF = 0;

    private BufferedImage buffer;
    private Timer timer;

    public Main(){

        buffer = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
        timer = new Timer(10, this);
        renderMandelBrotSet();

        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));
        timer.start();
    }

    public void renderMandelBrotSet() {
        System.out.println(XOFF);
        int vx = 0;
        int vy = 0;
        int zoom = 1;

        for(int x = 0; x < WIDTH; x++)
            for(int y = 0; y < HEIGHT; y++) {
                vx = ((x - WIDTH/2));
                vy = ((y - HEIGHT/2));
                vx = vx + XOFF;
                vy = vy + 0;
                int color = (int) (Math.abs(vx)/Math.sqrt(Math.abs(vy))*(vx/zoom));    //calculatePoint((x - WIDTH/2), (y - HEIGHT/2) );

                buffer.setRGB(x, y, color);
            }
    }


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

    @Override
    public void actionPerformed(ActionEvent e) {
        XOFF++;
        renderMandelBrotSet();
        revalidate();
        repaint();
    }
}

我希望代码有意义...,如果我忘记提任何事情,我感到抱歉。随时问我是否需要什么。

1 个答案:

答案 0 :(得分:1)

我认为addNotify是您的问题。该方法已经可以执行某些操作,而您覆盖它的方式似乎并没有执行其文档说明应执行的任何操作。只需摆脱它,然后将其代码移至其他位置即可。

这似乎对我有用。我也将您的计时器降低到100毫秒,因为我从经验中知道Java Swing确实没有那么快的更新能力。 100 ms至250 ms是更新Swing的合适范围。

我还摆脱了revalidate,因为这仅适用于添加或删除组件或更改大小的情况。您只需要重新绘画,因为图像不会改变大小。

(气垫船指出,代码确实应该覆盖paintComponent,而不是paint。他是非常正确的;在教程https://docs.oracle.com/javase/tutorial/uiswing/painting/closer.html中对此进行了解释)

(并且在修复问题时,我还应该指出Swing is not thread safe,和GUI的创建(包括图像和计时器)确实需要在GUI线程上完成。)

package quicktest;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.Timer;

/**
 *
 * @author Brenden
 */
public class MandelbrotSet {

}


class Main extends JComponent implements ActionListener {

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

    public static final int WIDTH = 800;
    public static final int HEIGHT = 600;
    public int XOFF = 0;
    public int YOFF = 0;

    private BufferedImage buffer;
    private Timer timer;


    public Main(){
       SwingUtilities.invokeLater( this::createGui );
    }

    private void createGui() {
        buffer = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
        timer = new Timer(100, this);
        setPreferredSize( new Dimension( WIDTH, HEIGHT ) );
        renderMandelBrotSet();

        JFrame frame = new JFrame("Mandelbrot Set");

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(true);
        frame.getContentPane().add(this);
        frame.pack();
        frame.setVisible(true);
        timer.start();
    }       

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

    public void renderMandelBrotSet() {
        System.out.println(XOFF);
        int vx = 0;
        int vy = 0;
        int zoom = 1;

        for(int x = 0; x < WIDTH; x++)
            for(int y = 0; y < HEIGHT; y++) {
                vx = ((x - WIDTH/2));
                vy = ((y - HEIGHT/2));
                vx = vx + XOFF;
                vy = vy + 0;
                int color = (int) (Math.abs(vx)/Math.sqrt(Math.abs(vy))*(vx/zoom));    //calculatePoint((x - WIDTH/2), (y - HEIGHT/2) );

                buffer.setRGB(x, y, color);
            }
    }

    @Override
    public void paintComponent(Graphics g) {
       super.paintComponent( g );
       System.err.println( "Repainting..." );
       g.drawImage(buffer, 0, 0, null);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
       System.err.println( "Timer: XOFF=" + XOFF );
        XOFF++;
        renderMandelBrotSet();
//        revalidate();
        repaint();
    }

}