Thread is failing to work in the required circumstances - java

In my code I have the following statements inside my Mouse Listener
class CustomMouseListener extends MouseAdapter {
Menu m;
MenuDesign mD;
SlideInLayout s;
public CustomMouseListener(Menu m, MenuDesign mD, SlideInLayout s) {
this.m = m;
this.mD = mD;
this.s = s;
}
public void mousePressed(MouseEvent mE) {
if(m != null && mD != null) {
if(mE.getSource() == mD) {
if(mD.getInOut()) {
mD.setFade(false);
Thread runSwap = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
s.show(m.getFirstPanel());
}
});
runSwap.start();
try {
runSwap.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
mD.setFade(true);
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
s.show(m.getOverlay());
}
}).start();
}
mD.fade();
m.getMainWindow().validate();
m.getMainWindow().repaint();
}
}
}
}
Ideally I would like my runnable animation to run at the same time as mD.fade(); so to do this I would write
Thread runSwap = new Thread(new Runnable() {
public void run() {
s.show(m.getFirstPanel());
}
});
instead of this.
Thread runSwap = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
s.show(m.getFirstPanel());
}
});
However this causes the end result of the animation to happen instantly. The other problem is that when I need to repaint the screen at the end as it ends up like the first frame in the picture below instead of the second frame however using the repaint() and validate() methods causes the animation in the runnable not to happen and the end result just appears again, even after a .join() is used with the thread.
I would appreciate any help in fixing the problem
Full Code if needed
package menutest;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class Menu {
JFrame myMainWindow = new JFrame("Menu Slide Test");
GridBagConstraints c;
MyFirstPanel fP;
MyOverlay oL;
MyMenuButton mB;
GridBagLayout baseLayout;
GridBagLayout overlayLayout;
SlideInLayout slideIn = new SlideInLayout();
JPanel tempHold = new JPanel(slideIn);
/* Height and Width */
int height = 600;
int width = 600;
private void runGUI(Menu m) {
myMainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myMainWindow.setLayout(new GridBagLayout());
setContraints();
createPanels(m);
myMainWindow.getContentPane().add(tempHold, c);
myMainWindow.getContentPane().add(mB, c, 0);
slideIn.show(fP);
myMainWindow.pack();
myMainWindow.setVisible(true);
myMainWindow.setLocationRelativeTo(null);
}
private void setContraints() {
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.weightx = 1;
c.weighty = 1;
c.fill = GridBagConstraints.BOTH;
}
private void createPanels(Menu m) {
createFirstPanel(m);
createOverlay(m);
createMenuButton(m);
tempHold.add(fP);
tempHold.add(oL);
}
private void createFirstPanel(Menu m) {
baseLayout = new GridBagLayout();
fP = new MyFirstPanel(baseLayout, m);
}
private void createOverlay(Menu m) {
overlayLayout = new GridBagLayout();
oL = new MyOverlay(overlayLayout, m);
}
private void createMenuButton(Menu m) {
mB = new MyMenuButton(m);
}
public static void main(String[] args) {
Menu menu = new Menu();
menu.runGUI(menu);
}
/* Getters and Setters */
public JPanel getFirstPanel() {
return fP;
}
public JPanel getOverlay() {
return oL;
}
public JFrame getMainWindow() {
return myMainWindow;
}
public int myGetHeight() {
return height;
}
public int myGetWidth() {
return width;
}
public SlideInLayout getSlide() {
return slideIn;
}
}
class MyFirstPanel extends JPanel {
/**
*
*/
private static final long serialVersionUID = 2897488186622284953L;
MyFirstPanel(GridBagLayout layout, Menu mM) {
setLayout(layout);
setBackground(Color.RED);
setPreferredSize(new Dimension(mM.myGetWidth(), mM.myGetHeight()));
}
}
class MyOverlay extends JPanel {
/**
*
*/
private static final long serialVersionUID = 4595122972358754430L;
MyOverlay(GridBagLayout layout, Menu mM) {
setLayout(layout);
setBackground(Color.GREEN);
setPreferredSize(new Dimension(mM.myGetWidth(), mM.myGetHeight()));
}
}
class MyMenuButton extends JPanel {
/**
*
*/
private static final long serialVersionUID = -4986432081497113479L;
MyMenuButton(Menu mM) {
setLayout(null);
setBackground(new Color(0, 0, 0, 0));
setPreferredSize(new Dimension(mM.myGetWidth(), mM.myGetHeight()));
add(new MenuDesign(15, 15, mM, mM.myGetWidth()));
}
}
class MenuDesign extends JLabel {
/**
*
*/
private static final long serialVersionUID = 2255075501909089222L;
boolean inOut = false; //true for fade out, false for fade in
//starts on false because it changes to true on first click on label
float alpha = 1F;
Timer timer;
//Start Points
double[] r1Points = {0, 6.67766953};
double[] r2Points = {0, 16.67766953};
double[] r3Points = {0, 26.67766953};
//Current Points
double[] curR1Points = {r1Points[0], r1Points[1]};
double[] curR3Points = {r3Points[0], r3Points[1]};
//End Points
double[] endR1Points = {2.828427125, 0};
double[] endR3Points = {0, 35.35533906};
//Angles
double ang1 = 0;
double ang2 = 0;
//Height and width of component to make it as efficient as possible
int width = 50;
int height = 40;
MenuDesign(int x, int y, Menu m, int width) {
setBounds(x, y, this.width, height);
setCursor(new Cursor(Cursor.HAND_CURSOR));
addMouseListener(new CustomMouseListener(m, this, m.getSlide()));
timer = new Timer(5, new CustomActionListener(m, this, r1Points, r3Points, endR1Points, endR3Points, x, width - 60));
}
public void fade() {
timer.start();
System.out.println("Start");
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setColor(Color.WHITE);
Rectangle2D r1 = new Rectangle2D.Double(curR1Points[0], curR1Points[1], width, 4);
Rectangle2D r2 = new Rectangle2D.Double(r2Points[0], r2Points[1], width, 4);
Rectangle2D r3 = new Rectangle2D.Double(curR3Points[0], curR3Points[1], width, 4);
//r1
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1F));
g2d.rotate(Math.toRadians(ang1), endR1Points[0], endR1Points[1]);
g2d.fill(r1);
//r3
g2d.rotate(Math.toRadians(-ang1), endR1Points[0], endR1Points[1]);
g2d.rotate(Math.toRadians(-ang2), endR3Points[0], endR3Points[1]);
g2d.fill(r3);
//r2
g2d.rotate(Math.toRadians(ang2), endR3Points[0], endR3Points[1]);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
g2d.fill(r2);
}
public Timer getTimer() {
return timer;
}
public float getAlpha() {
return alpha;
}
public void setAplha(float a) {
this.alpha = a;
if(a < 0) {
setAplha(0F);
}
if(a > 1) {
setAplha(1F);
}
validate();
repaint();
}
public boolean getInOut() {
return inOut;
}
public void setFade(boolean b) {
this.inOut = b;
}
public double[] getTransR1() {
return curR1Points;
}
public double[] getTransR3() {
return curR3Points;
}
public void setTransR1(double[] d) {
this.curR1Points = d;
}
public void setTransR3(double[] d) {
this.curR3Points = d;
}
public void setAng1(double d) {
this.ang1 = d;
}
public void setAng2(double d) {
this.ang2 = d;
}
public void stopTheTimer(int i) {
if(i == 101) {
timer.stop();
System.out.println("stop");
}
}
}
class CustomActionListener implements ActionListener {
Menu m;
MenuDesign mD;
MyFirstPanel mFP;
double[] a, b, c, d;
double incrementX1;
double incrementY1;
double incrementX2;
double incrementY2;
double incrementX3;
double incrementY3;
double incrementX4;
double incrementY4;
double angInc = 45.0 / 100.0;
double moveInc;
int i = 0;
int startPoint;
public CustomActionListener(Menu m, MyFirstPanel mFP) {
this.m = m;
this.mFP = mFP;
}
public CustomActionListener(Menu m, MenuDesign mD, double[] a, double[] b, double[] c, double[] d, int startPoint, int endPoint) {
this.m = m;
this.mD = mD;
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.startPoint = startPoint;
//Increments
int incTot = 100;
//r1 increments
incrementX1 = (c[0] - a[0]) / incTot;
incrementY1 = (c[1] - a[1]) / incTot;
incrementX2 = (a[0] - c[0]) / incTot;
incrementY2 = (a[1] - c[1]) / incTot;
//r2 increments
incrementX3 = (d[0] - b[0]) / incTot;
incrementY3 = (d[1] - b[1]) / incTot;
incrementX4 = (b[0] - d[0]) / incTot;
incrementY4 = (b[1] - d[1]) / incTot;
//Movement
moveInc = (endPoint - startPoint) / incTot;
}
public void actionPerformed(ActionEvent e) {
if(m != null && mD != null) {
if(e.getSource() == mD.getTimer()) {
if(mD.getInOut()) { //Start of transform into x
//r1
mD.setTransR1(new double[] {a[0] + (i * incrementX1), a[1] + (i * incrementY1)});
mD.setAng1(i * angInc);
//r2
mD.setAplha(mD.getAlpha() - 0.02F);
//r3
mD.setTransR3(new double[] {b[0] + (i * incrementX3), b[1] + (i * incrementY3)});
mD.setAng2(i * angInc);
//Location
mD.setLocation((int) (startPoint + (i * moveInc)), startPoint);
i++;
} else { //Start of transform into three lines
//r1
mD.setTransR1(new double[] {c[0] + (i * incrementX2), c[1] + (i * incrementY2)});
mD.setAng1((100 - i) * angInc);
//r2
if(i >= 50) {
mD.setAplha(mD.getAlpha() + 0.02F);
}
//r3
mD.setTransR3(new double[] {d[0] + (i * incrementX4), d[1] + (i * incrementY4)});
mD.setAng2((100 - i) * angInc);
//Location
mD.setLocation((int) (540 + (i * -moveInc)), 15);
i++;
}
if(i == 101) {
mD.stopTheTimer(i);
i = 0;
}
m.getMainWindow().validate();
m.getMainWindow().repaint();
}
}
}
}
class CustomMouseListener extends MouseAdapter {
Menu m;
MenuDesign mD;
SlideInLayout s;
public CustomMouseListener(Menu m, MenuDesign mD, SlideInLayout s) {
this.m = m;
this.mD = mD;
this.s = s;
}
public void mousePressed(MouseEvent mE) {
if(m != null && mD != null) {
if(mE.getSource() == mD) {
if(mD.getInOut()) {
mD.setFade(false);
Thread runSwap = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
s.show(m.getFirstPanel());
}
});
runSwap.start();
try {
runSwap.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
mD.setFade(true);
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
s.show(m.getOverlay());
}
}).start();
}
mD.fade();
m.getMainWindow().validate();
m.getMainWindow().repaint();
}
}
}
}
/////////////// Below here is not my code
class SlideInLayout implements LayoutManager {
private Component focusedComponent;
#Override
public void addLayoutComponent(String name, Component comp) {}
#Override
public void removeLayoutComponent(Component comp) {}
#Override
public void layoutContainer(Container parent) {
setSizes(parent);
if (hasFocusedComponent()) {
focusedComponent.setVisible(true);
}
}
private void setSizes(Container parent) {
Insets insets = parent.getInsets();
int maxWidth = parent.getWidth() - (insets.left + insets.right);
int maxHeight = parent.getHeight() - (insets.top + insets.bottom);
for (Component component : parent.getComponents()) {
component.setBounds(0, 0, maxWidth, maxHeight);
}
}
#Override
public Dimension minimumLayoutSize(Container parent) {
return new Dimension(0, 0);
}
#Override
public Dimension preferredLayoutSize(Container parent) {
Dimension preferredSize = new Dimension(0, 0);
if (hasFocusedComponent()) {
preferredSize = focusedComponent.getPreferredSize();
}
else if (parent.getComponentCount() > 0) {
int maxWidth = 0;
int maxHeight = 0;
for (Component component : parent.getComponents()) {
Dimension componentSize = component.getPreferredSize();
maxWidth = Math.max(maxWidth, componentSize.width);
maxHeight = Math.max(maxHeight, componentSize.height);
}
preferredSize = new Dimension(maxWidth, maxHeight);
}
return preferredSize;
}
private boolean hasFocusedComponent() {
return focusedComponent != null;
}
public void show(Component component) {
if (hasFocusedComponent())
swap(focusedComponent, component);
focusedComponent = component;
}
private void swap(Component transitionOut, Component transitionIn) {
new SwapTimerAction(transitionOut, transitionIn).start();
}
private class SwapTimerAction implements ActionListener {
private Timer timer;
private Component transitionOut;
private Component transitionIn;
private static final int tick = 16; //16ms
private static final int speed = 50;
public SwapTimerAction(Component transitionOut, Component transitionIn) {
this.transitionOut = transitionOut;
this.transitionIn = transitionIn;
}
public void start() {
Container container = transitionOut.getParent();
container.setComponentZOrder(transitionOut, 1);
container.setComponentZOrder(transitionIn, 0);
transitionIn.setBounds(-transitionOut.getWidth(), 0, transitionOut.getWidth(), transitionOut.getHeight());
timer = new Timer(tick, this);
timer.start();
}
#Override
public void actionPerformed(ActionEvent e) {
int newX = Math.min(transitionIn.getX() + speed, transitionOut.getX());
transitionIn.setLocation(newX, 0);
if (newX == transitionOut.getX()) {
timer.stop();
}
}
}
}

Related

How to prevent my Mandelbrotset code from getting blurry

I have written the mandelbrotset in java,but if i want to zoom into it it gets blurry after around 14 clicks, no matter the Maxiterration number, if its 100 it gets blurry and if its 100000 it gets blurry after 14 zoom ins.Something i noticed is that after i zoom in twice, all of the next zoom ins are instant in contrast to the first two which usually take a few seconds, this may help finding the solution. The code:
import java.util.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.math.BigDecimal;
public class test extends JFrame {
static final int WIDTH = 400;
static final int HEIGHT = WIDTH;
Canvas canvas;
BufferedImage fractalImage;
static final int MAX_ITER = 10000;
static final BigDecimal DEFAULT_TOP_LEFT_X = new BigDecimal(-2.0);
static final BigDecimal DEFAULT_TOP_LEFT_Y = new BigDecimal(1.4);
static final double DEFAULT_ZOOM = Math.round((double) (WIDTH/3));
final int numThreads = 10;
double zoomFactor = DEFAULT_ZOOM;
BigDecimal topLeftX = DEFAULT_TOP_LEFT_X;
BigDecimal topLeftY = DEFAULT_TOP_LEFT_Y;
BigDecimal z_r = new BigDecimal(0.0);
BigDecimal z_i = new BigDecimal(0.0);
// -------------------------------------------------------------------
public test() {
setInitialGUIProperties();
addCanvas();
canvas.addKeyStrokeEvents();
updateFractal();
this.setVisible(true);
}
// -------------------------------------------------------------------
public static void main(String[] args) {
new test();
}
// -------------------------------------------------------------------
private void addCanvas() {
canvas = new Canvas();
fractalImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
canvas.setVisible(true);
this.add(canvas, BorderLayout.CENTER);
} // addCanvas
// -------------------------------------------------------------------
private void setInitialGUIProperties() {
this.setTitle("Fractal Explorer");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(WIDTH, HEIGHT);
this.setResizable(false);
this.setLocationRelativeTo(null);
} // setInitialGUIProperties
// -------------------------------------------------------------------
private BigDecimal getXPos(double x) {
return topLeftX.add(new BigDecimal(x/zoomFactor));
} // getXPos
// -------------------------------------------------------------------
private BigDecimal getYPos(double y) {
return topLeftY.subtract(new BigDecimal(y/zoomFactor));
} // getYPos
// -------------------------------------------------------------------
/**
* Aktualisiert das Fraktal, indem die Anzahl der Iterationen für jeden Punkt im Fraktal berechnet wird und die Farbe basierend darauf geändert wird.
**/
public void updateFractal() {
Thread[] threads = new Thread[numThreads];
int rowsPerThread = HEIGHT / numThreads;
// Construct each thread
for (int i=0; i<numThreads; i++) {
threads[i] = new Thread(new FractalThread(i * rowsPerThread, (i+1) * rowsPerThread));
}
// Starte jeden thread
for (int i=0; i<numThreads; i++) {
threads[i].start();
}
// Warten bis alle threads fertig sind
for (int i=0; i<numThreads; i++) {
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
canvas.repaint();
} // updateFractal
// -------------------------------------------------------------------
//Gibt basierend auf der Iterationsanzahl eine trennungsfarbe zurück eines gegebenen Punktes im Fraktal
private class FractalThread implements Runnable {
int startY;
int endY;
public FractalThread(int startY, int endY) {
this.startY = startY;
this.endY = endY;
}
public void run() {
BigDecimal c_r;
BigDecimal c_i;
for (int x = 0; x < WIDTH; x++ ) {
for (int y = startY; y < endY; y++ ) {
c_r = getXPos(x);
c_i = getYPos(y);
int iterCount = computeIterations(c_r, c_i);
int pixelColor = makeColor(iterCount);
fractalImage.setRGB(x, y, pixelColor);
}
System.out.println(x);
}
} // run
} // FractalThread
private int makeColor( int iterCount ) {
int color = 0b011011100001100101101000;
int mask = 0b000000000000010101110111;
int shiftMag = iterCount / 13;
if (iterCount == MAX_ITER)
return Color.BLACK.getRGB();
return color | (mask << shiftMag);
} // makeColor
// -------------------------------------------------------------------
private int computeIterations(BigDecimal c_r, BigDecimal c_i) {
BigDecimal z_r = new BigDecimal(0.0);
BigDecimal z_i = new BigDecimal(0.0);
BigDecimal z_r_tmp = z_r;
BigDecimal dummy2 = new BigDecimal(2.0);
int iterCount = 0;
while ( z_r.doubleValue()*z_r.doubleValue() + z_i.doubleValue()*z_i.doubleValue() <= 4.0 ) {
z_r_tmp = z_r;
z_r = z_r.multiply(z_r).subtract(z_i.multiply(z_r)).add(c_r);
z_i = z_i.multiply(dummy2).multiply(z_i).multiply(z_r_tmp).add(c_i);
if (iterCount >= MAX_ITER) return MAX_ITER;
iterCount++;
}
return iterCount;
} // computeIterations
// -------------------------------------------------------------------
private void moveUp() {
double curHeight = HEIGHT / zoomFactor;
topLeftY = topLeftY.add(new BigDecimal(curHeight / 6));
updateFractal();
} // moveUp
// -------------------------------------------------------------------
private void moveDown() {
double curHeight = HEIGHT / zoomFactor;
topLeftY = topLeftY.subtract(new BigDecimal(curHeight / 6));
updateFractal();
} // moveDown
// -------------------------------------------------------------------
private void moveLeft() {
double curWidth = WIDTH / zoomFactor;
topLeftX = topLeftX.subtract(new BigDecimal(curWidth / 6));
updateFractal();
} // moveLeft
// -------------------------------------------------------------------
private void moveRight() {
double curWidth = WIDTH / zoomFactor;
topLeftX = topLeftX.add(new BigDecimal(curWidth / 6));;
updateFractal();
} // moveRight
// -------------------------------------------------------------------
private void adjustZoom( double newX, double newY, double newZoomFactor ) {
topLeftX = topLeftX.add(new BigDecimal(newX/zoomFactor));
topLeftY = topLeftY.subtract(new BigDecimal(newX/zoomFactor));
zoomFactor = newZoomFactor;
topLeftX = topLeftX.subtract(new BigDecimal(( WIDTH/2) / zoomFactor));
topLeftY = topLeftY.add(new BigDecimal( (HEIGHT/2) / zoomFactor));
updateFractal();
} // adjustZoom
// -------------------------------------------------------------------
private class Canvas extends JPanel implements MouseListener {
public Canvas() {
addMouseListener(this);
}
#Override public Dimension getPreferredSize() {
return new Dimension(WIDTH, HEIGHT);
} // getPreferredSize
#Override public void paintComponent(Graphics drawingObj) {
drawingObj.drawImage( fractalImage, 0, 0, null );
} // paintComponent
#Override public void mousePressed(MouseEvent mouse) {
double x = (double) mouse.getX();
double y = (double) mouse.getY();
switch( mouse.getButton() ) {
//Links
case MouseEvent.BUTTON1:
adjustZoom( x, y, zoomFactor*10 );
break;
// Rechts
case MouseEvent.BUTTON3:
adjustZoom( x, y, zoomFactor/2 );
break;
}
} // mousePressed
public void addKeyStrokeEvents() {
KeyStroke wKey = KeyStroke.getKeyStroke(KeyEvent.VK_W, 0 );
KeyStroke aKey = KeyStroke.getKeyStroke(KeyEvent.VK_A, 0 );
KeyStroke sKey = KeyStroke.getKeyStroke(KeyEvent.VK_S, 0 );
KeyStroke dKey = KeyStroke.getKeyStroke(KeyEvent.VK_D, 0 );
Action wPressed = new AbstractAction() {
#Override public void actionPerformed(ActionEvent e) {
moveUp();
}
};
Action aPressed = new AbstractAction() {
#Override public void actionPerformed(ActionEvent e) {
moveLeft();
}
};
Action sPressed = new AbstractAction() {
#Override public void actionPerformed(ActionEvent e) {
moveDown();
}
};
Action dPressed = new AbstractAction() {
#Override public void actionPerformed(ActionEvent e) {
moveRight();
}
};
this.getInputMap().put( wKey, "w_key" );
this.getInputMap().put( aKey, "a_key" );
this.getInputMap().put( sKey, "s_key" );
this.getInputMap().put( dKey, "d_key" );
this.getActionMap().put( "w_key", wPressed );
this.getActionMap().put( "a_key", aPressed );
this.getActionMap().put( "s_key", sPressed );
this.getActionMap().put( "d_key", dPressed );
} // addKeyStrokeEvents
#Override public void mouseReleased(MouseEvent mouse){ }
#Override public void mouseClicked(MouseEvent mouse) { }
#Override public void mouseEntered(MouseEvent mouse) { }
#Override public void mouseExited (MouseEvent mouse) { }
} // Canvas
} // FractalExplorer
I updated the code to use BigDecimals, and tried using less heapspace, because i got a few errors because of it, but know the for loop with x which picks a color just stops when the value of x equals 256-258, and if i change the width/height, then the program stops at around half of the width+an eight of the width.
I did more testing, and it stops at computIterations(...);, i don't know why, but i hope this helps. It seems like it doesn't stop but rather slow down after a certain amount of times.
I finnaly solved it. The code:
import java.util.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.math.BigDecimal;
public class FractalExplorer2 extends JFrame {
static final int WIDTH = 400;
static final int HEIGHT = WIDTH;
Canvas canvas;
BufferedImage fractalImage;
static final int MAX_ITER = 1000;
static final BigDecimal DEFAULT_TOP_LEFT_X = new BigDecimal(-2.0);
static final BigDecimal DEFAULT_TOP_LEFT_Y = new BigDecimal(1.4);
static final double DEFAULT_ZOOM = Math.round((double) (WIDTH/3));
static final int SCALE = 20;
static final int ROUND = BigDecimal.ROUND_CEILING;
final int numThreads = 10;
double zoomFactor = DEFAULT_ZOOM;
BigDecimal topLeftX = DEFAULT_TOP_LEFT_X;
BigDecimal topLeftY = DEFAULT_TOP_LEFT_Y;
// -------------------------------------------------------------------
public FractalExplorer2() {
long a = System.nanoTime();
setup();
addCanvas();
canvas.addKeyStrokeEvents();
updateFractal();
this.setVisible(true);
long b = System.nanoTime();
System.out.println((b-a));
}
// -------------------------------------------------------------------
public static void main(String[] args) {
new FractalExplorer2();
}
// -------------------------------------------------------------------
private void addCanvas() {
canvas = new Canvas();
fractalImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
canvas.setVisible(true);
this.add(canvas, BorderLayout.CENTER);
} // addCanvas
// -------------------------------------------------------------------
private void setup() {
this.setTitle("Fractal Explorer");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(WIDTH, HEIGHT);
this.setResizable(false);
this.setLocationRelativeTo(null);
} // setInitialGUIProperties
// -------------------------------------------------------------------
private BigDecimal getXPos(double x) {
return topLeftX.add(new BigDecimal(x/zoomFactor));
} // getXPos
// -------------------------------------------------------------------
private BigDecimal getYPos(double y) {
return topLeftY.subtract(new BigDecimal(y/zoomFactor));
} // getYPos
// -------------------------------------------------------------------
/**
* Aktualisiert das Fraktal, indem die Anzahl der Iterationen für jeden Punkt im Fraktal berechnet wird und die Farbe basierend darauf geändert wird.
**/
public void updateFractal() {
Thread[] threads = new Thread[numThreads];
int rowsPerThread = HEIGHT / numThreads;
// Construct each thread
for (int i=0; i<numThreads; i++) {
threads[i] = new Thread(new FractalThread(i * rowsPerThread, (i+1) * rowsPerThread));
}
// Starte jeden thread
for (int i=0; i<numThreads; i++) {
threads[i].start();
}
// Warten bis alle threads fertig sind
for (int i=0; i<numThreads; i++) {
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
canvas.repaint();
} // updateFractal
// -------------------------------------------------------------------
//Gibt basierend auf der Iterationsanzahl eine trennungsfarbe zurück eines gegebenen Punktes im Fraktal
private class FractalThread implements Runnable {
int startY;
int endY;
public FractalThread(int startY, int endY) {
this.startY = startY;
this.endY = endY;
}
public void run() {
BigDecimal c_r;
BigDecimal c_i;
for (int x = 0; x < WIDTH; x++ ) {
for (int y = startY; y < endY; y++ ) {
c_r = getXPos(x);
c_i = getYPos(y);
int iterCount = computeIterations(c_r, c_i);
int pixelColor = makeColor(iterCount);
fractalImage.setRGB(x, y, pixelColor);
}
}
} // run
} // FractalThread
private int makeColor( int iterCount ) {
int color = 0b011011100001100101101000;
int mask = 0b000000000000010101110111;
int shiftMag = iterCount / 13;
if (iterCount == MAX_ITER)
return Color.BLACK.getRGB();
return color | (mask << shiftMag);
} // makeColor
// -------------------------------------------------------------------
private int computeIterations(BigDecimal c_r, BigDecimal c_i) {
BigDecimal z_r = new BigDecimal(0.0).setScale(SCALE,ROUND);
BigDecimal z_i = new BigDecimal(0.0).setScale(SCALE,ROUND);
BigDecimal z_r_tmp;
BigDecimal dummy2 = new BigDecimal(2.0).setScale(SCALE,ROUND);
BigDecimal dummy4 = new BigDecimal(4.0).setScale(SCALE,ROUND);
int iterCount = 0;
while (z_r.multiply(z_r).add((z_i.multiply(z_i))).compareTo(dummy4) != 1) {
z_r_tmp = z_r.setScale(SCALE,ROUND);
z_r = z_r.multiply(z_r).subtract(z_i.multiply(z_i)).add(c_r).setScale(SCALE,ROUND);
z_i = dummy2.multiply(z_i).multiply(z_r_tmp).add(c_i).setScale(SCALE,ROUND);
if (iterCount >= MAX_ITER) return MAX_ITER;
iterCount++;
}
return iterCount;
} // computeIterations
// -------------------------------------------------------------------
private void moveUp() {
double curHeight = HEIGHT / zoomFactor;
topLeftY = topLeftY.add(new BigDecimal(curHeight / 6));
updateFractal();
} // moveUp
// -------------------------------------------------------------------
private void moveDown() {
double curHeight = HEIGHT / zoomFactor;
topLeftY = topLeftY.subtract(new BigDecimal(curHeight / 6));
updateFractal();
} // moveDown
// -------------------------------------------------------------------
private void moveLeft() {
double curWidth = WIDTH / zoomFactor;
topLeftX = topLeftX.subtract(new BigDecimal(curWidth / 6));
updateFractal();
} // moveLeft
// -------------------------------------------------------------------
private void moveRight() {
double curWidth = WIDTH / zoomFactor;
topLeftX = topLeftX.add(new BigDecimal(curWidth / 6));
updateFractal();
} // moveRight
// -------------------------------------------------------------------
private void adjustZoom( double newX, double newY, double newZoomFactor ) {
topLeftX = topLeftX.add(new BigDecimal(newX/zoomFactor)).setScale(SCALE,ROUND);
topLeftY = topLeftY.subtract(new BigDecimal(newY/zoomFactor)).setScale(SCALE,ROUND);
zoomFactor = newZoomFactor;
topLeftX = topLeftX.subtract(new BigDecimal(( WIDTH/2) / zoomFactor)).setScale(SCALE,ROUND);
topLeftY = topLeftY.add(new BigDecimal( (HEIGHT/2) / zoomFactor)).setScale(SCALE,ROUND);
updateFractal();
} // adjustZoom
// -------------------------------------------------------------------
private class Canvas extends JPanel implements MouseListener {
public Canvas() {
addMouseListener(this);
}
#Override public Dimension getPreferredSize() {
return new Dimension(WIDTH, HEIGHT);
} // getPreferredSize
#Override public void paintComponent(Graphics drawingObj) {
drawingObj.drawImage( fractalImage, 0, 0, null );
} // paintComponent
#Override public void mousePressed(MouseEvent mouse) {
double x = (double) mouse.getX();
double y = (double) mouse.getY();
switch( mouse.getButton() ) {
//Links
case MouseEvent.BUTTON1:
adjustZoom( x, y, zoomFactor*5 );
break;
// Rechts
case MouseEvent.BUTTON3:
adjustZoom( x, y, zoomFactor/2 );
break;
}
} // mousePressed
public void addKeyStrokeEvents() {
KeyStroke wKey = KeyStroke.getKeyStroke(KeyEvent.VK_W, 0 );
KeyStroke aKey = KeyStroke.getKeyStroke(KeyEvent.VK_A, 0 );
KeyStroke sKey = KeyStroke.getKeyStroke(KeyEvent.VK_S, 0 );
KeyStroke dKey = KeyStroke.getKeyStroke(KeyEvent.VK_D, 0 );
Action wPressed = new AbstractAction() {
#Override public void actionPerformed(ActionEvent e) {
moveUp();
}
};
Action aPressed = new AbstractAction() {
#Override public void actionPerformed(ActionEvent e) {
moveLeft();
}
};
Action sPressed = new AbstractAction() {
#Override public void actionPerformed(ActionEvent e) {
moveDown();
}
};
Action dPressed = new AbstractAction() {
#Override public void actionPerformed(ActionEvent e) {
moveRight();
}
};
this.getInputMap().put( wKey, "w_key" );
this.getInputMap().put( aKey, "a_key" );
this.getInputMap().put( sKey, "s_key" );
this.getInputMap().put( dKey, "d_key" );
this.getActionMap().put( "w_key", wPressed );
this.getActionMap().put( "a_key", aPressed );
this.getActionMap().put( "s_key", sPressed );
this.getActionMap().put( "d_key", dPressed );
} // addKeyStrokeEvents
#Override public void mouseReleased(MouseEvent mouse){ }
#Override public void mouseClicked(MouseEvent mouse) { }
#Override public void mouseEntered(MouseEvent mouse) { }
#Override public void mouseExited (MouseEvent mouse) { }
} // Canvas
} // FractalExplorer
I just replaced the double variables with BigDecimal and set a Scale, so that the calculation doesn't take too long. I think the code can still be improved, but this is my code right now.

I try to use the method repaint after paintComponent but its not work

First it will be a little longer because I want to show all the code I have done until now, so excuse me..
This is my first time in java.
I'm trying to build an aquarium with fish and jellyfish drawing and use threads.
When I try to add animal I want to paint it but without success, I built PaintComponent method but when I try to use repaint I can not draw..
What am I missing?
It looks that way, when I click on Add Animal window opens , I choose the values and after I click OK, need to draw the animal
I hope that the rest of what I did was okay .. thank you so much for helping!
paintComponent and repaint is at AquaPanel Class.
public class AquaFrame extends JFrame {
private AquaPanel mPanel;
private JLabel label1;
private ImageIcon icon;
private BufferedImage imag;
public AquaFrame() {
super("my Aquarium");
setLayout(new BorderLayout());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(700, 600);
setResizable(false);
setVisible(true);
setLocationRelativeTo(null);
mPanel = new AquaPanel(getGraphics());
add(mPanel);
}
public void buildFrame(){
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu file = new JMenu("File");
menuBar.add(file);
JMenuItem exItem = new JMenuItem("Exit");
file.add(exItem);
exItem.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
JMenu background = new JMenu("Background");
menuBar.add(background);
JMenuItem blue = new JMenuItem("Blue");
blue.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
mPanel.setBackground(Color.BLUE);
}
});
JMenuItem none = new JMenuItem("None");
none.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
mPanel.setBackground(null);
}
});
JMenuItem image = new JMenuItem("Image");
image.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
imag = ImageIO.read(new File("aquarium_background.jpg"));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
background.add(image);
background.add(blue);
background.add(none);
JMenu help = new JMenu("Help");
JMenuItem helpItem = new JMenuItem("help");
helpItem.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null,"GUI # Threads");
}
});
menuBar.add(help);
help.add(helpItem);
setVisible(true);
}
public void paint(Graphics g){
g.drawImage(imag, 0, 0, null);
}
public static void main(String[] args) {
AquaFrame mFrame = new AquaFrame();
mFrame.buildFrame();
}
}
/******************************************/
public class AquaPanel extends JPanel {
private JFrame infoTableFrame;
private JTable infoTable;
private Set<Swimmable > swimmables = new HashSet<Swimmable>();
private AddAnimalDialog animalDialog;
private int totalEatCounter;
private Graphics g;
public AquaPanel(Graphics g) {
this.g = g;
totalEatCounter = 0;
infoTableFrame = new JFrame();
infoTableFrame.setVisible(false);
setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.PAGE_END;
constraints.weighty = 1;
JButton btAdd = new JButton("Add Animal");
btAdd.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (swimmables.size() >= 5)
{
JOptionPane.showMessageDialog(null, "You can't have more than 5 animals at the same time.");
}
else
{
animalDialog = new AddAnimalDialog(AquaPanel.this);
animalDialog.setVisible(true);
}
}
});
JButton btSleep = new JButton("Sleep");
btSleep.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (Swimmable swimmable : swimmables)
{
swimmable.setSuspend();
}
}
});
JButton btWakeup = new JButton("Wake Up");
btWakeup.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (Swimmable swimmable : swimmables)
{
swimmable.setResume();
}
}
});
JButton btRst = new JButton("Reset");
btRst.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (Swimmable swimmable : swimmables)
{
swimmable.kill();
}
swimmables.clear();
}
});
JButton btFood = new JButton("Food");
btFood.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (swimmables.size() > 0)
{
CyclicBarrier barrier = new CyclicBarrier(swimmables.size());
for (Swimmable swimmable : swimmables)
{
swimmable.setBarrier(barrier);
swimmable.setFood(true);
}
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(3));
g2.setColor(Color.red);
g2.drawArc(getWidth() / 2, getHeight() / 2 - 5, 10, 10, 30, 210);
g2.drawArc(getWidth()/2, getHeight()/2+5, 10, 10, 180, 270);
g2.setStroke(new BasicStroke(1));
}
}
});
JButton btInfo = new JButton("Info");
btInfo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
showInfoTable();
}
});
JButton btExit = new JButton("Exit");
btExit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
add(btAdd,constraints);
add(btSleep,constraints);
add(btWakeup,constraints);
add(btRst,constraints);
add(btFood,constraints);
add(btInfo,constraints);
add(btExit,constraints);
}
public void showInfoTable(){
if (infoTableFrame.isVisible())
{
infoTableFrame.remove(infoTable);
infoTableFrame.setVisible(false);
}
else
{
String[] col = {"Animal","Color","Size","Hor.speed","Ver.speed","Eat counter"};
String[][] data = new String[swimmables.size()][col.length];
int i=0;
for (Swimmable swimmable : swimmables)
{
data[i][0] = swimmable.getAnimalName();
data[i][1] = swimmable.getColor();
data[i][2] = "" + swimmable.getSize();
data[i][3] = "" + swimmable.getHorSpeed();
data[i][4] = "" + swimmable.getVerSpeed();
data[i][5] = "" + swimmable.getEatCount();
++i;
}
infoTable = new JTable(data, col);
//TODO - not overriding values
JScrollPane jPane = new JScrollPane(infoTable);
infoTableFrame.add(jPane, BorderLayout.CENTER);
infoTableFrame.setSize(300, 150);
infoTableFrame.setVisible(true);
}
}
public void addAnimal(Swimmable animal)
{
animal.setAquaPanel(this);
swimmables.add(animal);
animal.run();
//myrepaint();
/**********************************/
repaint();
/**********************************/
}
public void onEatFood(Swimmable eater)
{
eater.eatInc();
++totalEatCounter;
for (Swimmable swimmable : swimmables)
{
swimmable.setFood(false);
}
}
/*public void myrepaint()
{
for (Swimmable swimmable : swimmables)
{
swimmable.drawAnimal(g);
}
}*/
/************************************************/
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Swimmable swimmable : swimmables)
{
swimmable.drawAnimal(g);
}
}
/*********************************************/
}
public abstract class Swimmable extends Thread {
protected AquaPanel aquaPanel;
protected boolean isFood;
protected boolean isSuspended;
protected int horSpeed;
protected int verSpeed;
protected int x_dir, y_dir;
protected int eatCount;
protected CyclicBarrier barrier;
protected int x0, y0;
protected boolean isAlive;
public Swimmable() {
horSpeed = 0;
verSpeed = 0;
x_dir = 1;
y_dir = 1;
eatCount = 0;
}
public Swimmable(int hor, int ver) {
horSpeed = hor;
verSpeed = ver;
x_dir = 1;
y_dir = 1;
eatCount = 0;
}
#Override
public void run() {
isAlive = true;
while (isAlive) {
try {
sleep(10);
if (isSuspended)
{
wait();
}
else
{
if (isFood)
{
barrier.await();
updateFrontsTowardsFood();
if (isNearFood())
{
aquaPanel.onEatFood(this);
}
}
else
{
updateFronts();
}
//aquaPanel.myrepaint();
aquaPanel.repaint();
}
}
catch (Exception e)
{
//TODO - handle exception
}
}
}
public void kill()
{
isAlive = false;
}
public int getHorSpeed() {
return horSpeed;
}
public int getVerSpeed() {
return verSpeed;
}
public void setHorSpeed(int hor) {
horSpeed = hor;
}
public void setVerSpeed(int ver) {
verSpeed = ver;
}
abstract public int getSize();
abstract public String getColor();
public void setSuspend()
{
isSuspended = true;
}
public void setResume()
{
isSuspended = false;
}
public void eatInc()
{
++eatCount;
}
public int getEatCount()
{
return eatCount;
}
public void setBarrier(CyclicBarrier b)
{
barrier = b;
}
public void setFood(boolean isFood)
{
this.isFood = isFood;
}
public void setAquaPanel(AquaPanel panel)
{
aquaPanel = panel;
x0 = aquaPanel.getWidth() / 2;
y0 = aquaPanel.getHeight() / 2;
}
abstract public String getAnimalName();
abstract public void drawAnimal(Graphics g);
abstract protected void updateFronts();
abstract protected void updateFrontsTowardsFood();
abstract protected boolean isNearFood();
}
public class Fish extends Swimmable {
protected int x_front , y_front;
private int size;
private Color color;
public Fish(Color col, int sz, int hor, int ver) {
super(hor, ver);
size = sz;
color = col;
x_front = 0;
y_front = 0;
}
public void drawAnimal(Graphics g) {
g.setColor(color);
if (x_dir == 1) // fish swims to right side
{
// Body of fish
g.fillOval(x_front - size, y_front - size / 4, size, size / 2);
// Tail of fish
int[] x_t = { x_front - size - size / 4, x_front - size - size / 4, x_front - size };
int[] y_t = { y_front - size / 4, y_front + size / 4, y_front };
Polygon t = new Polygon(x_t, y_t, 3);
g.fillPolygon(t);
// Eye of fish
Graphics2D g2 = (Graphics2D) g;
g2.setColor(new Color(255 - color.getRed(),255 - color.getGreen(),255- color .getBlue()));
g2.fillOval(x_front-size/5, y_front-size/10, size/10, size/10);
//Mouth of fish
if(size>70)
g2.setStroke(new BasicStroke(3));
else if(size>30)
g2.setStroke(new BasicStroke(2));
else
g2.setStroke(new BasicStroke(1));
g2.drawLine(x_front, y_front, x_front-size/10, y_front+size/10);
g2.setStroke(new BasicStroke(1));
}
else // fish swims to left side
{
// Body of fish
g.fillOval(x_front, y_front - size / 4, size, size / 2);
// Tail of fish
int[] x_t = { x_front + size + size / 4, x_front + size + size / 4, x_front + size };
int[] y_t = { y_front - size / 4, y_front + size / 4, y_front };
Polygon t = new Polygon(x_t, y_t, 3);
g.fillPolygon(t);
// Eye of fish
Graphics2D g2 = (Graphics2D) g;
g2.setColor(new Color(255 - color.getRed(), 255 - color.getGreen(), 255 - color.getBlue()));
g2.fillOval(x_front+size/10, y_front-size/10, size/10, size/10);
// Mouth of fish
if (size > 70)
g2.setStroke(new BasicStroke(3));
else if (size > 30)
g2.setStroke(new BasicStroke(2));
else
g2.setStroke(new BasicStroke(1));
g2.drawLine(x_front, y_front, x_front + size / 10, y_front + size / 10);
g2.setStroke(new BasicStroke(1));
}
}
public String getAnimalName() {
return "Fish";
}
public int getSize() {
return size;
}
public String getColor() {
if (color == Color.RED)
return "RED";
else if (color == Color.GREEN)
return "GREEN";
else if (color == Color.ORANGE)
return "ORANGE";
else
return "UNKNOWN";
}
protected void updateFronts()
{
x_front += x_dir * horSpeed;
y_front += y_dir * verSpeed;
if (x_front > x0*2 || x_front < 0)
x_dir *= -1;
if (y_front > y0*2 || y_front < 0)
y_dir *= -1;
}
protected void updateFrontsTowardsFood()
{
//TODO - copy from word
}
protected boolean isNearFood()
{
return ((Math.abs(x_front-x0) <= 5) && (Math.abs(y_front-y0) <= 5));
}
}
public class Jellyfish extends Swimmable {
private int x_front , y_front;
private int size;
private Color color;
public Jellyfish(Color col, int sz, int hor, int ver) {
super(hor, ver);
size = sz;
color = col;
x_front = 0;
y_front = 0;
}
public void drawAnimal(Graphics g) {
int numLegs;
if (size < 40)
numLegs = 5;
else if (size < 80)
numLegs = 9;
else
numLegs = 12;
g.setColor(color);
g.fillArc(x_front - size / 2, y_front - size / 4, size, size / 2, 0, 180);
for (int i = 0; i < numLegs; i++)
g.drawLine(x_front - size / 2 + size / numLegs + size * i / (numLegs + 1), y_front,
x_front - size / 2 + size / numLegs + size * i / (numLegs + 1), y_front + size / 3);
}
public String getAnimalName() {
return "Jellyfish";
}
public int getSize() {
return size;
}
public String getColor() {
if (color == Color.RED)
return "RED";
else if (color == Color.GREEN)
return "GREEN";
else if (color == Color.ORANGE)
return "ORANGE";
else
return "UNKNOWN";
}
public void updateFronts()
{
x_front += x_dir * horSpeed;
y_front += y_dir * verSpeed;
if (x_front > x0*2 || x_front < 0)
x_dir *= -1;
if (y_front > y0*2 || y_front < 0)
y_dir *= -1;
}
protected void updateFrontsTowardsFood()
{
//TODO - copy from word
}
protected boolean isNearFood()
{
return ((Math.abs(x_front-x0) <= 5) && (Math.abs(y_front-y0) <= 5));
}
}
public class AddAnimalDialog extends JDialog {
private JButton btOk, btCancel;
private JTextField tfSize, tfHspeed, tfVspeed;
private ButtonGroup groupType, groupColor;
private JRadioButton rbFish, rbJellyfish, rbRed, rbGreen, rbOrange;
JPanel panel;
public AddAnimalDialog(AquaPanel aquaPanel) {
this.setLayout(new FlowLayout());
panel = new JPanel();
panel.setLayout(new GridLayout(10, 20));
panel.add(new JLabel("Size(20-320): "));
panel.add(tfSize = new JTextField());
panel.add(new JLabel("Horizontal speed(1-10): "));
panel.add(tfHspeed = new JTextField());
panel.add(new JLabel("Vertical speed(1-10): "));
panel.add(tfVspeed = new JTextField());
panel.add(new JLabel("Type: "));
panel.add(new JLabel(" "));
panel.add(rbFish = new JRadioButton("fish"));
panel.add(rbJellyfish = new JRadioButton("jellyfish"));
panel.add(new JLabel("Color: "));
panel.add(new JLabel(" "));
panel.add(rbRed = new JRadioButton("Red"));
panel.add(rbGreen = new JRadioButton("Green"));
panel.add(rbOrange = new JRadioButton("Orange"));
// Group the radio buttons.
groupType = new ButtonGroup();
groupType.add(rbFish);
groupType.add(rbJellyfish);
rbFish.setSelected(true);
groupColor = new ButtonGroup();
groupColor.add(rbRed);
groupColor.add(rbGreen);
groupColor.add(rbOrange);
rbRed.setSelected(true);
panel.add(new JLabel(""));
panel.add(btOk = new JButton("OK"));
panel.add(btCancel = new JButton("Cancel"));
this.add(panel);
this.setLocationRelativeTo(null);
this.setResizable(false);
this.pack();
this.btOk.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
int size = Integer.parseInt(tfSize.getText());
int hSpeed = Integer.parseInt(tfHspeed.getText());
int vSpeed = Integer.parseInt(tfVspeed.getText());
if (checkValues(size, hSpeed, vSpeed)) {
Color clr = Color.RED;
if (rbRed.isSelected()) {
clr = Color.RED;
} else if (rbGreen.isSelected()) {
clr = Color.GREEN;
} else if (rbOrange.isSelected()) {
clr = Color.ORANGE;
} else {
JOptionPane.showMessageDialog(null, "You must choose a color!");
}
if (rbFish.isSelected()) {
setVisible(false);
aquaPanel.addAnimal(new Fish(clr, size, hSpeed, vSpeed));
} else if (rbJellyfish.isSelected()) {
setVisible(false);
aquaPanel.addAnimal(new Jellyfish(clr, size, hSpeed, vSpeed));
} else {
JOptionPane.showMessageDialog(null, "You must choose animal type!");
}
}
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null, "One of the number values has wrong format, please check it");
}
}
});
this.btCancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
setVisible(false);
System.out.println("Click the Close button if you want to stop adding windows");
}
});
}
private boolean checkValues(int size, int hspeed, int vspeed) {
if ((size > 320 || size < 20) || (hspeed < 1 || hspeed > 10) || (vspeed < 1 || vspeed > 10)) {
JOptionPane.showMessageDialog(null, "One of the values is out of bounds, please follow the restrictions.");
return false;
}
return true;
}
}
There are a number of basic problems...
The main problem is with your Swimmable run method, it is blocking the Event Dispatching Thread, preventing it from been able to respond to UI events, including repaint events. See Concurrency in Java for more details.
You should NEVER use getGraphics, apart from been able to return null, anything you paint to it is painted outside of the normal paint cycle and will painted over the next time component is repainted. See Painting in AWT and Swing and Performing Custom Painting for more details.
Your current approach won't scale well, the more fish you add, the more resources they will consume and will affect the ability for the program to keep up with all the different changes and repaint requests.
A better solution would be to have a single "update" loop which takes care of telling each of the Swimmables that it needs to update and then schedules a single repaint each cycle. Personally, I'd start with a Swing Timer as it "ticks" within the EDT, making it much safer to modify the state of the objects which the paintComponent method needs.
See How to use Swing Timers for more details
I would suggest having a look at this, which basically describes what you're trying to do and what I'm suggesting you should do instead
Try calling repaint in your JFrame class after calling the addAnimal method. There is also revalidate() method in there as well and their difference is in this article: Java Swing revalidate() vs repaint()

Background image in different place every time

I have a large program that I will post some classes of and hopefully you guys can find the problem. Basically, sometimes when I start it, it creates the game just fine, and others the background is up a few pixels to the north and west directions leaving very unsightly whitespace. I cannot seem to find the missing piece of code that decides whether not it does this. It honestly feel like some kind of rendering glitch on my machine. At any rate, I have put a background getX and getY method in for debugging and have noticed that whether the background is fully stretched to the screen(its a custom background so the pixel height and width match perfectly), or its up and to the left, the background still reads that it is displaying at (0,0). I will post all the methods from the main thread to the creating of the background in the menu. I will leave notes indicating the path it takes through this code that gets it to creating the background. Thank you for your help and I will check in regularly for edits and more information.
EDIT: added background.java
EDIT2: added pictures explaining problem
Menu.java *ignore the FileIO code, the main point is the creation of a new GamePanel()
public class Menu {
private static File file;
public static void main(String[] args) throws IOException {
file = new File("saves.txt");
if(file.exists()){
FileIO.run();
FileIO.profileChoose();
}
else{
FileIO.profileCreate();
FileIO.run();
}
JFrame window = new JFrame("Jolly Jackpot Land");
window.setContentPane(new GamePanel());
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setResizable(false);
window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
}
}
Next is the GamePanel.java
public class GamePanel extends JPanel implements Runnable, KeyListener {
// ID
private static final long serialVersionUID = 1L;
// Dimensions
public static final int WIDTH = 320;
public static final int HEIGHT = 240;
public static final int SCALE = 2;
// Thread
private Thread thread;
private boolean running;
private int FPS = 30;
private long targetTime = 1000 / FPS;
// Image
private BufferedImage image;
private Graphics2D g;
// Game State Manager
private GameStateManager gsm;
public GamePanel() {
super();
setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setFocusable(true);
requestFocus();
}
public void addNotify() {
super.addNotify();
if (thread == null) {
thread = new Thread(this);
addKeyListener(this);
thread.start();
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
}
private void init() {
image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) image.getGraphics();
running = true;
gsm = new GameStateManager();
}
#Override
public void run() {
init();
long start;
long elapsed;
long wait;
// Game Loop
while (running) {
start = System.nanoTime();
update();
draw();
drawToScreen();
elapsed = System.nanoTime() - start;
wait = targetTime - (elapsed / 1000000);
if (wait < 0) {
wait = 5;
}
try {
Thread.sleep(wait);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void update() {
gsm.update();
}
private void draw() {
gsm.draw(g);
}
private void drawToScreen() {
Graphics g2 = getGraphics();
g2.drawImage(image, 0, 0, WIDTH * SCALE, HEIGHT * SCALE, null);
g2.dispose();
}
#Override
public void keyPressed(KeyEvent k) {
gsm.keyPressed(k.getKeyCode());
}
#Override
public void keyReleased(KeyEvent k) {
}
#Override
public void keyTyped(KeyEvent arg0) {
}
}
This calls for the creation of a new GameStateManager object in its init() method and the class for that is here.
GameStateManager.java
public class GameStateManager {
private ArrayList<GameState> gameStates;
private int currentState;
public static final int MENUSTATE = 0;
public static final int SLOTGAMESTATE = 1;
public static final int DICEGAMESTATE = 2;
public static final int ROULETTEGAMESTATE = 3;
public static final int LEADERBOARDSTATE = 4;
public static final int SETTINGSSTATE = 5;
public static final int HELPSTATE = 6;
public GameStateManager() {
gameStates = new ArrayList<GameState>();
currentState = 0;
gameStates.add(new MenuState(this));
gameStates.add(new SlotGameState(this));
gameStates.add(new DiceGameState(this));
gameStates.add(new RouletteGameState(this));
gameStates.add(new LeaderboardState(this));
gameStates.add(new SettingsState(this));
gameStates.add(new HelpState(this));
}
public void setState(int state){
currentState = state;
gameStates.get(currentState).init();
currentState = 0;
}
public int getState() {
return currentState;
}
public void update() {
gameStates.get(currentState).init();
}
public void draw(java.awt.Graphics2D g){
gameStates.get(currentState).draw(g);
}
public void keyPressed(int k){
gameStates.get(currentState).keyPressed(k);
}
public void keyReleased(int k) {
gameStates.get(currentState).keyReleased(k);
}
}
GameState is an abstract class I have so its not worth posting, it only contains init(), draw(), etc. This next class is the last and final class and is called because GameStateMananger starts at MENUSTATE or 0, and when GSM is initialized it initializes its current state, thus taking us to the class MenuState
MenuState.java
public class MenuState extends GameState {
private Background bg;
public FontMetrics fontMetrics;
private int choice = 0;
private String[] options = { "Slot Machine", "Dice Toss", "Roulette Wheel", "Leaderboards", "Settings", "Help",
"Quit" };
private Color titleColor;
private Font titleFont;
private Font font;
public MenuState(GameStateManager gsm) {
this.gsm = gsm;
try {
bg = new Background("/Backgrounds/happybg.png");
titleColor = Color.WHITE;
titleFont = new Font("Georgia", Font.PLAIN, 28);
} catch (Exception e) {
e.printStackTrace();
}
font = new Font("Arial", Font.PLAIN, 12);
}
#Override
public void init() {
}
#Override
public void update() {
}
#Override
public void draw(Graphics2D g) {
Canvas c = new Canvas();
fontMetrics = c.getFontMetrics(font);
// Draw BG
bg.draw(g);
// Draw title
g.setColor(titleColor);
g.setFont(titleFont);
String title = "Jolly Jackpot Land!";
g.drawString(title, 36, 60);
g.setFont(font);
for (int i = 0; i < options.length; i++) {
if (i == choice)
g.setColor(Color.RED);
else
g.setColor(Color.WHITE);
g.drawString(options[i], 30, 120 + i * 15);
}
g.setColor(Color.WHITE);
g.setFont(new Font("Arial", Font.PLAIN, 10));
g.drawString("v1.1", 165, 235);
Object[] a = { ("Name: " + Player.getName()), ("Gil: " + Player.getGil()),
("Personal Best: " + Player.getPersonalBest()), ("Winnings: " + Player.getWinnings()),
("Wins: " + Player.getWins()), ("Losses: " + Player.getLosses()),
("Win/Loss Ratio: " + String.format("%.2f", Player.getRatio()) + "%") };
g.setFont(font);
if (Player.getName() != null) {
for (int x = 0; x < a.length; x++) {
g.drawString(a[x].toString(), GamePanel.WIDTH - fontMetrics.stringWidth(a[x].toString()) - 30,
120 + x * 15);
}
}
}
private void select() {
if (choice == 0) {
// Slots
gsm.setState(GameStateManager.SLOTGAMESTATE);
}
if (choice == 1) {
// Dice
gsm.setState(GameStateManager.DICEGAMESTATE);
}
if (choice == 2) {
// Roulette
gsm.setState(GameStateManager.ROULETTEGAMESTATE);
}
if (choice == 3) {
// Leaderboards
gsm.setState(GameStateManager.LEADERBOARDSTATE);
}
if (choice == 4) {
// Settings
gsm.setState(GameStateManager.SETTINGSSTATE);
}
if (choice == 5) {
// Help
gsm.setState(GameStateManager.HELPSTATE);
}
if (choice == 6) {
// Quit
System.exit(0);
}
}
#Override
public void keyPressed(int k) {
if (k == KeyEvent.VK_ENTER) {
select();
}
if (k == KeyEvent.VK_UP) {
choice--;
if (choice == -1) {
choice = options.length - 1;
}
}
if (k == KeyEvent.VK_DOWN) {
choice++;
if (choice == options.length) {
choice = 0;
}
}
}
#Override
public void keyReleased(int k) {
}
}
Background.java
public class Background {
private BufferedImage image;
private double x;
private double y;
public Background(String s) {
try {
image = ImageIO.read(getClass().getResourceAsStream(s));
} catch (Exception e) {
e.printStackTrace();
}
}
public void setPosition(double x, double y) {
this.setX(x);
this.setY(y);
}
public void draw(Graphics2D g) {
g.drawImage(image, 0, 0, null);
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
}
This is where it waits for input in the game loop basically. I know this is a lot of code, but a lot of it is skimming till a method call takes you to the next class. I just can't figure out why it only happens sometimes, if it was consistent I could debug it. Any help would be extremely appreciated.
These are both from clicking the .jar of the above program, exact same .jar, exact same source code, different result. I am bewildered.

2 Observers (JInternalFrames) 1 Observable does not work

I have 3 classes. One class is my mainframe, another class is my JInternalFrame and also my Observer and the third class does a simulation with a field ob buttons and that one is also my observable class.
Basically I made a button in my observer that copies itself. That includes the add to the desktoppane and the addObserver function of my observable class.
The clone of my observer should also observer the very same observable. So if I interact with the one JInternalFrame, it also changes stuff for the other InternalFrame. It should act like a mirror. (Actually the copy should have like diffrent color buttons and a diffrent orientation but I think that should not be a problem to implement, as soon as I successfully could mirror my Observer)
So since I am using the Observable pattern, I also have to implement the "update" function in my Observer class. I did that and I works like a charm. But when I copy my JInternalFrame, the new InternalFrame observes the Observable(Simulation), but my original JInternalFrame loses the observable connection. It does not show buttons anymore etc.
What I tried: I created a second Observer/JInternalFrame class that extends my first Observer class. That did not work as well. I don't know if thats even a possibility to achieve what I want to.
Sorry for my non perfect english. Sorry for some german words that you might find in the code and sorry that I post so much code. But I am really uncertain right now where my mistake is since I tried to find the error for ours so far.
So here are 2 pictures for you:
First picture shows how my JInternalFrame looks like when I create it. Here everything works perfectly.
Second picture shows what it looks like when I click on the New View button. As already described. The original JInternalFrame does not show the simulation anymore. Although they are both observing the same Observable.
And here are my 3 imporant classes:
MainFrame:
public class LangtonsAmeise extends JFrame implements ActionListener {
JDesktopPane desk;
JPanel panelButtons;
JMenuBar jmb;
JMenu file, modus;
JMenuItem load, save, exit, mSetzen, mMalen, mLaufen;
JSlider slider;
static int xInt, yInt, xKindFrame = 450, yKindFrame = 450, xLocation,
yLocation, xMainFrame = 1000, yMainFrame = 900;
static boolean bSetzen = false, bMalen = false, running = true;
static JFileChooser fc;
Random randomGenerator = new Random();
JLabel xLabel, yLabel, speed, statusText, status;
JButton start, stop, addAnt;
JTextField xField, yField;
public LangtonsAmeise() {
// Desktop
desk = new JDesktopPane();
getContentPane().add(desk, BorderLayout.CENTER);
// File Chooser
fc = new JFileChooser(System.getProperty("user.dir"));
speed = new JLabel("Geschwindigkeit");
xLabel = new JLabel("x:");
yLabel = new JLabel("y:");
xLabel.setHorizontalAlignment(JLabel.RIGHT);
yLabel.setHorizontalAlignment(JLabel.RIGHT);
xLabel.setOpaque(true);
yLabel.setOpaque(true);
xField = new JTextField();
yField = new JTextField();
start = new JButton("Fenster erstellen");
stop = new JButton("Pause/Fortsetzen");
start.setMargin(new Insets(0, 0, 0, 0));
stop.setMargin(new Insets(0, 0, 0, 0));
// Buttons
panelButtons = new JPanel();
panelButtons.setLayout(new GridLayout());
panelButtons.add(start);
panelButtons.add(xLabel);
panelButtons.add(xField);
panelButtons.add(yLabel);
panelButtons.add(yField);
panelButtons.add(speed);
panelButtons.add(new Panel());
panelButtons.add(stop);
start.addActionListener(this);
stop.addActionListener(this);
add(panelButtons, BorderLayout.NORTH);
statusText = new JLabel("Status:");
status = new JLabel("Stopp");
// JMenuBar
jmb = new JMenuBar();
setJMenuBar(jmb);
file = new JMenu("File");
modus = new JMenu("Mode");
mLaufen = new JMenuItem("Laufen");
mMalen = new JMenuItem("Malen");
mSetzen = new JMenuItem("Setzen");
load = new JMenuItem("Simulation laden");
//save = new JMenuItem("Simulation speichern");
mSetzen.addActionListener(this);
mMalen.addActionListener(this);
mLaufen.addActionListener(this);
exit = new JMenuItem("Exit");
file.add(load);
file.addSeparator();
file.add(exit);
load.addActionListener(this);
modus.add(mLaufen);
modus.add(mSetzen);
modus.add(mMalen);
jmb.add(file);
jmb.add(modus);
for (int i = 0; i < 20; i++) {
jmb.add(new JLabel(" "));
}
jmb.add(statusText);
jmb.add(status);
setSize(new Dimension(xMainFrame, yMainFrame));
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
this.setLocation(dim.width / 2 - this.getSize().width / 2, dim.height
/ 2 - this.getSize().height / 2);
xField.setText("5");
yField.setText("5");
setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("Fenster erstellen")) {
if (xField.getText().equals("") || yField.getText().equals("")) {
} else {
xInt = Integer.parseInt(xField.getText());
yInt = Integer.parseInt(yField.getText());
state s = new state();
kindFenster k = new kindFenster(s, this);
s.addObserver(k);
addChild(k);
s.startSimulation();
}
}
if (e.getActionCommand().equals("Pause/Fortsetzen")) {
running = !running;
System.out.println(running);
status.setText("Stopp");
}
if (e.getActionCommand().equals("Setzen")) {
status.setText("Setzen");
running = false;
bSetzen = true;
bMalen = false;
}
if (e.getActionCommand().equals("Laufen")) {
status.setText("Laufen");
running = true;
bSetzen = false;
bMalen = false;
}
if (e.getActionCommand().equals("Malen")) {
status.setText("Malen");
running = false;
bSetzen = false;
bMalen = true;
}
if (e.getActionCommand().equals("Simulation laden")) {
LangtonsAmeise.running = false;
InputStream fis = null;
try {
fc.showOpenDialog(null);
fis = new FileInputStream(fc.getSelectedFile().getPath());
ObjectInputStream ois = new ObjectInputStream(fis);
state s = (state) ois.readObject();
kindFenster k = new kindFenster(s, this);
s.addObserver(k);
addChild(k);
s.startSimulation();
} catch (IOException | ClassNotFoundException
| NullPointerException e1) {
LangtonsAmeise.running = true;
} finally {
try {
fis.close();
} catch (NullPointerException | IOException e1) {
LangtonsAmeise.running = true;
}
}
LangtonsAmeise.running = true;
}
}
public void addChild(JInternalFrame kind) {
xLocation = randomGenerator.nextInt(xMainFrame - xKindFrame);
yLocation = randomGenerator.nextInt(yMainFrame - yKindFrame - 100);
kind.setSize(370, 370);
kind.setLocation(xLocation, yLocation);
desk.add(kind);
kind.setVisible(true);
}
public static void main(String[] args) {
LangtonsAmeise hauptFenster = new LangtonsAmeise();
}
}
JInternalFrame:
public class kindFenster extends JInternalFrame implements ActionListener,
Serializable,Observer,Cloneable {
/**
*
*/
private static final long serialVersionUID = 8939449766068226519L;
static int nr = 0;
static int x,y,xScale,yScale,xFrame,yFrame;
state s;
ArrayList<ImageIcon> ameisen = new ArrayList<ImageIcon>();
JFileChooser fc;
LangtonsAmeise la;
Color alteFarbe, neueFarbe;
JButton save, addAnt, newView;
JPanel panelButtonsKind;
JSlider sliderKind;
public JPanel panelSpielfeld,panelSpielfeldKopie;
JButton[] jbArrayy;
static SetzenActionListener sal = new SetzenActionListener();
static MouseMotionActionListener mmal = new MouseMotionActionListener();
public kindFenster(state s,LangtonsAmeise la) {
super("Kind " + (++nr), true, true, true, true);
setLayout(new BorderLayout());
this.s=s;
jbArrayy=new JButton[s.jbArrayy.length];
for (int b = 1; b<s.jbArrayy.length;b++) {
this.jbArrayy[b] = s.jbArrayy[b];
}
this.la=la;
setSize(new Dimension(xFrame, yFrame));
this.addInternalFrameListener(listener);
this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
panelSpielfeld = new JPanel();
panelSpielfeld.setLayout(new GridLayout(s.y, s.x));
panelButtonsKind = new JPanel();
panelButtonsKind.setLayout(new GridLayout(1, 3));
save = new JButton("<html>Save<br>simulation</html>");
addAnt = new JButton("<html>Add<br>ant</html>");
newView = new JButton("<html>New<br>View</html>");
save.setActionCommand("save");
addAnt.setActionCommand("addAnt");
newView.setActionCommand("newView");
save.setMargin(new Insets(0, 0, 0, 0));
addAnt.setMargin(new Insets(0, 0, 0, 0));
addAnt.addActionListener(this);
save.addActionListener(this);
newView.addActionListener(this);
sliderKind = new JSlider(JSlider.HORIZONTAL, 1, 9, 5);
sliderKind.setSnapToTicks(true);
sliderKind.setPaintTicks(true);
sliderKind.setPaintTrack(true);
sliderKind.setMajorTickSpacing(1);
sliderKind.setPaintLabels(true);
sliderKind.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
JSlider source = (JSlider) e.getSource();
if (!source.getValueIsAdjusting()) {
int speed = source.getValue();
state.sleeptime = 1000 / speed;
}
}
});
panelButtonsKind.add(save);
panelButtonsKind.add(newView);
panelButtonsKind.add(sliderKind);
panelButtonsKind.add(addAnt);
add(panelButtonsKind, BorderLayout.NORTH);
add(panelSpielfeld, BorderLayout.CENTER);
this.addComponentListener(new MyComponentAdapter());
for (int i = 1 ; i<jbArrayy.length;i++) {
panelSpielfeld.add(jbArrayy[i]);
}
}
// I have been trying around to change the orientation of the buttons in the copy of the frame
public void secondViewFrameSettings() {
int temp;
for (int i = 1; i<=x;i++) {
for (int k = 0; k<y;k++) {
temp = i+(k*x);
panelSpielfeldKopie.add(s.jbArrayy[temp]);
}
}
}
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("addAnt")) {
s.addAnt();
}
if (e.getActionCommand().equals("newView")){
kindFenster kk = new kindFenster(s,la);
s.addObserver(kk);
la.addChild(kk);
}
if (e.getActionCommand().equals("save")) {
OutputStream fos = null;
try {
LangtonsAmeise.running=false;
try {
fc = new JFileChooser(System.getProperty("user.dir"));
fc.showSaveDialog(null);
LangtonsAmeise.fc.setCurrentDirectory(fc.getSelectedFile());
fos = new FileOutputStream(fc.getSelectedFile());
ObjectOutputStream o = new ObjectOutputStream(fos);
o.writeObject(s);
} catch (NullPointerException e2) {
System.out.println("Fehler beim Auswählen der Datei. Wenden Sie sich an den Entwickler.");
}
} catch (IOException e1) {
LangtonsAmeise.running=true;
System.err.println(e1);
} finally {
try {
fos.close();
} catch (NullPointerException | IOException e1) {
LangtonsAmeise.running=true;
}
LangtonsAmeise.running=true;
}
LangtonsAmeise.running=true;
}
}
InternalFrameListener listener = new InternalFrameAdapter() {
public void internalFrameClosing(InternalFrameEvent e) {
e.getInternalFrame().dispose();
s.simulation.suspend();
}
};
class MyComponentAdapter extends ComponentAdapter {
public void componentResized(ComponentEvent e) {
//Ameisenbilder an die Buttongrößen anpassen
xScale=s.jbArrayy[1].getSize().width;
yScale=s.jbArrayy[1].getSize().height;
s.ameisen.clear();
s.ameisen.add(new ImageIcon(new ImageIcon("ameise.gif")
.getImage().getScaledInstance(xScale, yScale,
Image.SCALE_SMOOTH)));
s.ameisen.add(new ImageIcon(new ImageIcon("ameise90.gif")
.getImage().getScaledInstance(xScale, yScale,
Image.SCALE_SMOOTH)));
s.ameisen.add(new ImageIcon(new ImageIcon("ameise180.gif")
.getImage().getScaledInstance(xScale, yScale,
Image.SCALE_SMOOTH)));
s.ameisen.add(new ImageIcon(new ImageIcon("ameise270.gif")
.getImage().getScaledInstance(xScale, yScale,
Image.SCALE_SMOOTH)));
}
}
public void update(Observable o, Object arg) {
if (o == s) {
for (int i = 1;i<s.jbArrayy.length;i++) {
jbArrayy[i].setBackground(s.jbArrayy[i].getBackground());
}
}
}
}
class SetzenActionListener implements ActionListener,Serializable {
JButton source;
#Override
public void actionPerformed(ActionEvent e) {
source = (JButton) e.getSource();
if (LangtonsAmeise.bSetzen == true) {
if (source.getBackground().equals(Color.GREEN)) {
source.setBackground(Color.WHITE);
} else {
source.setBackground(Color.GREEN);
}
}
}
}
class MouseMotionActionListener extends MouseInputAdapter implements Serializable {
boolean dragged = false;
JButton tempJButton = new JButton();
public void mouseEntered(MouseEvent e) {
if (LangtonsAmeise.bMalen == true && dragged == true) {
((JButton) e.getSource()).setBackground(Color.GREEN);
}
}
public void mouseDragged(MouseEvent e) {
dragged = true;
}
public void mouseReleased(MouseEvent e) {
dragged = false;
}
}
Observable class:
public class state extends Observable implements Serializable {
/**
*
*/
private static final long serialVersionUID = 450773214079105589L;
int[] obRand, reRand, unRand, liRand;
int x, y, temp;
static int sleeptime = 200;
Color background;
int posAmeise, aktuellesIcon = 1, altePosAmeise, xScale, yScale;
Color alteFarbe, neueFarbe, color1, color2;
ArrayList<JButton> jbSer = new ArrayList<JButton>();
private List<Ant> ants = new ArrayList<Ant>();
ArrayList<ImageIcon> ameisen = new ArrayList<>();
JButton[] jbArrayy;
transient Thread simulation;
public state() {
this.x = LangtonsAmeise.xInt;
this.y = LangtonsAmeise.yInt;
color1 = Color.WHITE;
color2 = Color.GREEN;
jbArrayy = new JButton[x * y + 1];
initializeBorders();
initializeAntsImages();
initializeSimulationButtons();
xScale = jbArrayy[1].getSize().width;
yScale = jbArrayy[1].getSize().height;
// Startpunkt für die Ameise festlegen
posAmeise = (((x / 2) * y) - y / 2);
background = jbArrayy[posAmeise].getBackground();
ants.add(new Ant(this));
}
public void initializeAntsImages() {
ameisen.add(new ImageIcon(new ImageIcon("ameise.gif").getImage()
.getScaledInstance(LangtonsAmeise.xKindFrame / x,
LangtonsAmeise.yKindFrame / y, Image.SCALE_SMOOTH)));
ameisen.add(new ImageIcon(new ImageIcon("ameise90.gif").getImage()
.getScaledInstance(LangtonsAmeise.xKindFrame / x,
LangtonsAmeise.yKindFrame / y, Image.SCALE_SMOOTH)));
ameisen.add(new ImageIcon(new ImageIcon("ameise180.gif").getImage()
.getScaledInstance(LangtonsAmeise.xKindFrame / x,
LangtonsAmeise.yKindFrame / y, Image.SCALE_SMOOTH)));
ameisen.add(new ImageIcon(new ImageIcon("ameise270.gif").getImage()
.getScaledInstance(LangtonsAmeise.xKindFrame / x,
LangtonsAmeise.yKindFrame / y, Image.SCALE_SMOOTH)));
}
// Alle Buttons für das Simulationsfeld werden erstellt
public void initializeSimulationButtons() {
jbArrayy[0] = new JButton();
for (int i = 1; i < jbArrayy.length; i++) {
jbArrayy[i] = new JButton();
jbArrayy[i].setBackground(color1);
jbArrayy[i].addActionListener(kindFenster.sal);
jbArrayy[i].addMouseListener(kindFenster.mmal);
jbArrayy[i].addMouseMotionListener(kindFenster.mmal);
}
}
// Ränderindex in Array schreiben
public void initializeBorders() {
reRand = new int[y];
liRand = new int[y];
obRand = new int[x];
unRand = new int[x];
for (int i = 0; i < x; i++) {
obRand[i] = i + 1;
unRand[i] = (x * y - x) + i + 1;
}
for (int i = 1; i <= y; i++) {
reRand[i - 1] = i * x;
liRand[i - 1] = i * x - (x - 1);
}
}
public void initializeSimulation() {
if (simulation != null && simulation.isAlive()) {
simulation.stop();
}
simulation = new Thread() {
#Override
public void run() {
super.run();
while (true) {
try {
sleep(300);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
while (LangtonsAmeise.running && countObservers() > 0) {
try {
Thread.sleep(sleeptime);
for (Ant a : ants) {
move(a);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
};
}
public void startSimulation() {
initializeSimulation();
simulation.start();
}
public void changeColor(int altePos, Color c) {
jbArrayy[altePos].setBackground(c);
}
public void addAnt() {
ants.add(new Ant(this));
}
public void changeIcon(boolean k, Ant a) {
int g = (k == true) ? 1 : -1;
if (a.aktuellesIcon + g < 0) {
a.aktuellesIcon = 3;
} else if (a.aktuellesIcon + g > 3) {
a.aktuellesIcon = 0;
} else {
a.aktuellesIcon += g;
}
jbArrayy[a.posAmeise].setIcon(ameisen.get(a.aktuellesIcon));
setChanged();
notifyObservers();
}
public void rightCheck(Ant a) {
if (checkInArray(a.posAmeise, reRand)) {
a.posAmeise -= x - 1;
} else {
a.posAmeise += 1;
}
}
public void leftCheck(Ant a) {
if (checkInArray(a.posAmeise, liRand)) {
a.posAmeise += x - 1;
} else {
a.posAmeise -= 1;
}
}
public void upCheck(Ant a) {
if (checkInArray(a.posAmeise, obRand)) {
a.posAmeise += (y - 1) * x;
} else {
a.posAmeise -= x;
}
}
public void downCheck(Ant a) {
if (checkInArray(a.posAmeise, unRand)) {
a.posAmeise -= (y - 1) * x;
} else {
a.posAmeise += x;
}
}
public void checkAmeisenSize(Ant a) {
while (!(ameisen.size() == 4)) {
}
;
}
public static boolean checkInArray(int currentState, int[] myArray) {
int i = 0;
for (; i < myArray.length; i++) {
if (myArray[i] == currentState)
break;
}
return i != myArray.length;
}
public ImageIcon getAntImage() {
return ameisen.get(aktuellesIcon);
}
public void move(Ant a) throws InterruptedException {
try {
a.altePosAmeise = a.posAmeise;
a.alteFarbe = jbArrayy[a.posAmeise].getBackground();
if (a.alteFarbe.equals(Color.GREEN) && ameisen.size() == 4) {
if (a.aktuellesIcon == 0) {
checkAmeisenSize(a);
rightCheck(a);
} else if (a.aktuellesIcon == 1) {
checkAmeisenSize(a);
downCheck(a);
} else if (a.aktuellesIcon == 2) {
checkAmeisenSize(a);
leftCheck(a);
} else if (a.aktuellesIcon == 3) {
checkAmeisenSize(a);
upCheck(a);
}
changeIcon(true, a);
changeColor(a.altePosAmeise, Color.WHITE);
} else if (a.alteFarbe.equals(Color.WHITE) && ameisen.size() == 4) {
if (a.aktuellesIcon == 0) {
checkAmeisenSize(a);
leftCheck(a);
} else if (a.aktuellesIcon == 1) {
checkAmeisenSize(a);
upCheck(a);
} else if (a.aktuellesIcon == 2) {
checkAmeisenSize(a);
rightCheck(a);
} else if (a.aktuellesIcon == 3) {
checkAmeisenSize(a);
downCheck(a);
}
changeIcon(false, a);
changeColor(a.altePosAmeise, Color.GREEN);
setChanged();
notifyObservers();
}
jbArrayy[a.altePosAmeise].setIcon(new ImageIcon());
} catch (IndexOutOfBoundsException e) {
move(a);
}
}
}
Edit: Ant Class
import java.awt.Color;
import java.awt.Image;
import java.io.Serializable;
import java.util.ArrayList;
import javax.swing.ImageIcon;
public class Ant implements Serializable {
int posAmeise, aktuellesIcon = 1, altePosAmeise;
Color alteFarbe, neueFarbe;
ArrayList<ImageIcon> ameisen = new ArrayList<>();
public Ant(state s) {
this.posAmeise = s.posAmeise;
s.jbArrayy[posAmeise].setIcon(s.ameisen.get(aktuellesIcon));
}
}

Getting the error " Cannot find symbol " on getdocumentBase()

Despite I import the applet library, NetBeans cannot recognize and use getDocumentBase() in my code, I have my html file within my project and all other required files as well, here is a part of my code :
import java.awt.*;
import java.applet.*;
public class AirportCanvas extends Canvas
{
SingleLaneAirport controller;
Image redPlane;
Image bluePlane;
Image airport;
//AudioClip crashSound;
int[] redX,redY,blueX,blueY;
int maxCar = 2;
final static int initredX = 5;
final static int initredY = 55;
final static int initblueX = 410;
final static int initblueY = 130;
final static int bridgeY = 90;
boolean frozen = false;
int cycleTime = 20;
AirportCanvas(SingleLaneAirport controller)
{
super();
this.controller = controller;
// crashSound=controller.getAudioClip(controller.getDocumentBase(),"crash.au");
MediaTracker mt;
mt = new MediaTracker(this);
redPlane = controller.getImage(controller.getDocumentBase(), "redplane.png");
mt.addImage(redPlane, 0);
bluePlane = controller.getImage(controller.getDocumentBase(), "blueplane.png");
mt.addImage(bluePlane, 1);
airport = controller.getImage(controller.getDocumentBase(), "airport.png");
mt.addImage(airport, 2);
try
{
mt.waitForID(0);
mt.waitForID(1);
mt.waitForID(2);
}
catch (java.lang.InterruptedException e)
{
System.out.println("Couldn't load one of the images");
}
setSize(airport.getWidth(null),airport.getHeight(null));
init(1);
}
public final void init(int ncars)
{ //set number of cars
maxCar = ncars;
frozen = false;
redX = new int[maxCar];
redY = new int[maxCar];
blueX = new int[maxCar];
blueY = new int[maxCar];
for (int i = 0; i<maxCar ; i++)
{
redX[i] = initredX - i*85;
redY[i] = initredY;
blueX[i] =initblueX + i*85;
blueY[i] =initblueY;
}
repaint();
}
Image offscreen;
Dimension offscreensize;
Graphics offgraphics;
public void backdrop()
{
Dimension d = getSize();
if ((offscreen == null) || (d.width != offscreensize.width)
|| (d.height != offscreensize.height))
{
offscreen = createImage(d.width, d.height);
offscreensize = d;
offgraphics = offscreen.getGraphics();
offgraphics.setFont(new Font("Helvetica",Font.BOLD,36));
}
offgraphics.setColor(Color.lightGray);
offgraphics.drawImage(airport,0,0,this);
}
#Override
public void paint(Graphics g)
{
update(g);
}
#Override
public void update(Graphics g)
{
backdrop();
for (int i=0; i<maxCar; i++)
{
offgraphics.drawImage(redPlane,redX[i],redY[i],this);
offgraphics.drawImage(bluePlane,blueX[i],blueY[i],this);
}
if (blueY[0]==redY[0] && Math.abs(redX[0]+80 - blueX[0])<5)
{
offgraphics.setColor(Color.red);
offgraphics.drawString("Crunch!",200,100);
frozen=true;
// crashSound.play();
}
g.drawImage(offscreen, 0, 0, null);
}
//returns true for the period from just before until just after car on bridge
public boolean moveRed(int i) throws InterruptedException
{
int X = redX[i];
int Y = redY[i];
synchronized (this)
{
while (frozen )
wait();
if (i==0 || Math.abs(redX[i-1] - X) > 120)
{
X += 2;
if (X >=500)
{
X = -80; Y = initredY;
}
if (X >=60 && X < 290 && Y<bridgeY)
++Y;
if (X >=290 && Y>initredY)
--Y;
}
redX[i]=X;
redY[i]=Y;
repaint();
}
Thread.sleep(cycleTime);
return (X>25 && X<400);
}
//returns true for the period from just before until just after car on bridge
public boolean moveBlue(int i) throws InterruptedException
{
int X = blueX[i];
int Y = blueY[i];
synchronized (this)
{
while (frozen )
wait();
if (i==0 || Math.abs(blueX[i-1] - X) > 120)
{
X -= 2;
if (X <=-80)
{
X = 500; Y = initblueY;
}
if (X <=370 && X > 130 && Y>bridgeY)
--Y;
if (X <=130 && Y<initblueY)
++Y;
blueX[i]=X;
}
blueY[i]=Y;
repaint();
}
Thread.sleep(cycleTime);
repaint();
return (X>25 && X<400);
}
public synchronized void freeze()
{
frozen = true;
}
public synchronized void thaw()
{
frozen = false;
notifyAll();
}
}
Single Lane Airport Class :
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class SingleLaneAirport {
AirportCanvas display;
Button restart;
Button freeze;
Button onecar;
Button twocar;
Button threecar;
Checkbox fair;
Checkbox safe;
boolean fixed = false;
int maxCar = 1;
Thread red[];
Thread blue[];
#Override
public void init()
{
setLayout(new BorderLayout());
display = new AirportCanvas(this);
add("Center",display);
restart = new Button("Restart");
restart.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
display.thaw();
}
});
freeze = new Button("Freeze");
freeze.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
display.freeze();
}
});
onecar = new Button("One Car");
onecar.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
stop();
maxCar = 1;
start();
}
});
twocar = new Button("Two Cars");
twocar.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
stop();
maxCar = 2;
start();
}
});
threecar = new Button("Three Cars");
threecar.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
stop();
maxCar = 3;
start();
}
});
safe = new Checkbox("Safe",null,true);
safe.setBackground(Color.lightGray);
safe.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent e)
{
stop();
start();
}
});
fair = new Checkbox("Fair",null,false);
fair.setBackground(Color.lightGray);
fair.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent e)
{
stop();
start();
}
});
Panel p1 = new Panel();
p1.setLayout(new FlowLayout());
p1.add(freeze);
p1.add(restart);
p1.add(onecar);
p1.add(twocar);
p1.add(threecar);
p1.add(safe);
p1.add(fair);
add("South",p1);
setBackground(Color.lightGray);
}
#Override
public void start()
{
red = new Thread[maxCar];
blue = new Thread[maxCar];
display.init(maxCar);
Airport b;
if (fair.getState() && safe.getState())
b = new FairAirport();
else if ( safe.getState())
b = new SafeAirport();
else
b = new Airport();
for (int i = 0; i<maxCar; i++)
{
red[i] = new Thread(new RedPlane(b,display,i));
blue[i] = new Thread(new BluePlane(b,display,i));
}
for (int i = 0; i<maxCar; i++)
{
red[i].start();
blue[i].start();
}
}
#Override
public void stop()
{
for (int i = 0; i<maxCar; i++)
{
red[i].interrupt();
blue[i].interrupt();
}
}
}
Your class SingleLaneAirport should extend Applet class in order to use getDocumentBase() function.
Because getDocumentBase() is the function of Applet class and not the Object class

Categories

Resources