I am very new to developing with java but I have some general coding experience. 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. 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 ^^
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. 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 ms to 250 ms is a good range for updating Swing.
I also got rid of revalidate
because that's only for when a component is added or removed, or changes size. 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 )
(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.)
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();
}
}