简体   繁体   English

更改变量时重绘不起作用

[英]Repaint doesn't work when changing variable

I am very new to developing with java but I have some general coding experience. 我对使用Java开发非常陌生,但是我有一些通用的编码经验。 I know wanted to draw a "picture/fractal" with a function I created. 我知道想用我创建的功能绘制“图片/分形”。 I got all the code done and I wanted to automatically move the "fractal" by just adding to the function XOFF, (I have a timer) now I wanted the variable to automatically increase so that it scrolls through the picture. 我完成了所有代码,我想通过仅向函数XOFF添加(我有一个计时器)来自动移动“分形”,现在我希望变量自动增加以使其在图片中滚动。 I tried using repaint and revalidate but it doesnt work :( 我尝试使用重新绘制和重新验证,但它不起作用:(

and i know that i wrote MandelBrotSet even though it doesn't have anything to do with it ^^ 而且我知道我写了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();
    }
}

I hope the code makes sense..., I am sorry if I forgot to mention anything. 我希望代码有意义...,如果我忘记提任何事情,我感到抱歉。 Feel free to ask me if you need something. 随时问我是否需要什么。

I think addNotify is your problem. 我认为addNotify是您的问题。 That method already does something, and the way you overrode it you don't seem to perform any of the actions that its documentation says it should. 该方法已经可以执行某些操作,而您覆盖它的方式似乎并没有执行其文档说明应执行的任何操作。 Just get rid of it, and move its code elsewhere. 只需摆脱它,然后将其代码移至其他位置即可。

This seems to work for me. 这似乎为我工作。 I also slowed your timer down to 100 ms since I know from experience that Java Swing isn't really capable of updating as quickly as that. 我也将您的计时器降低到100毫秒,因为我从经验中知道Java Swing确实没有那么快的更新能力。 100 ms to 250 ms is a good range for updating Swing. 100 ms至250 ms是更新Swing的合适范围。

I also got rid of revalidate because that's only for when a component is added or removed, or changes size. 我还摆脱了revalidate因为这仅适用于添加或删除组件或更改大小的情况。 You only need to repaint since your image doesn't change size. 由于图像不会更改大小,因此只需要重新绘画。

(Hovercraft pointed out that the code really should override paintComponent , not paint . He is quite correct; this is explained in the tutorial: https://docs.oracle.com/javase/tutorial/uiswing/painting/closer.html ) (Hovercraft指出,代码确实应该覆盖paintComponent ,而不是paint 。他是非常正确的;在教程中对此进行了解释: https : //docs.oracle.com/javase/tutorial/uiswing/painting/closer.html

(And while I'm fixing stuff up I might as well point out that Swing is not thread safe, and the GUI creation (including the image and the timer) really needs to be done on the GUI thread.) (在修复问题时,我可能还指出, Swing不是线程安全的,并且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();
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM