I'm kind of new to Java and OO programming, here is the code of moving black and white balls problem. First let me explain the program that I want in the output: there are n balls(for example 6 balls) on the window, one black and one white, in each move we only are allowed to move just one ball and this movement should be shown on the screen, and at the end all the white balls should be on one side and all the black balls should be on the other side. Here is an example of six balls:
I have written the program and it seems working good and no flaws in the algorithm, but my problem is that I can't show animation of the movement of the balls, in each movement one ball should swap its place with its neighbor ball, but all I get is the final arrangements of the balls. Please someone help me with the animation part. I would be really thankful for that.
code:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.*;
public class DrawPanel extends JPanel implements ActionListener
{
Timer myTimer = new Timer(2000, this);
public static final int NUMBER_OF_CIRCLES = 10; //number of circles which are to moved
static int[] circles = new int[NUMBER_OF_CIRCLES];
public void paintComponent(Graphics g)
{
int x = 0; //start point of circles;
int length = 40; //diagonal of the circles
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Ellipse2D circle;
//painting n circles based on the array
for(int index = 0; index<10; index++)
{
if(circles[index] == 0){ //if the element of the arrayy is 0 then draw a void circle
circle = new Ellipse2D.Double(x, 120, length, length);
g2.draw(circle);
}
else if(circles[index] == 1){ //if the element of the array is 1 them draw a filled circle
circle = new Ellipse2D.Double(x, 120, length, length);
g2.fill(circle);
}
x += 45; //increas start pont of the next circle 45 pixles
}
myTimer.start();
}
public void actionPerformed(ActionEvent e)
{
int tmp; //template for swaping elements
int condition; //condition of the forS
arrayFill(circles); //fills the array based on the writen method, one 1 and one 0 like: 0 1 0 1 0 1 0 1
//here is the part which works good, it changes palces of an elemen at time.
//at the end of this part the array would be like: 1 1 1 1 0 0 0 0
if(NUMBER_OF_CIRCLES % 2 == 0)
condition = circles.length/2 -1;
else
condition = circles.length/2;
for(int i = circles.length-1, k = 1; i>condition; i--, k++)
{
for(int j = i - k; j<i ;j++)
{
tmp = circles[j];
circles[j] = circles[j+1];
circles[j+1] = tmp;
//if we call arrayPrint method it will print the array but I don't know why repaint is not working here
//arrayPrint(circles);
repaint();
}
}
}
//fills the array, one 1 and one 0. Example: 0 1 0 1 0 1 0 1 0 1
public static void arrayFill(int[] array)
{
for(int i = 0; i<array.length; i++)
{
if( i%2 == 0)
array[i] = 0;
else
array[i] = 1;
}
}
}//end of class
And the main Class:
import javax.swing.JFrame;
public class BlackAndWhiteBallsMoving {
public static void main(String[] args)
{
DrawPanel myPanel = new DrawPanel();
JFrame myFrame = new JFrame();
myFrame.add(myPanel);
myFrame.setSize(600, 500);
myFrame.setTitle("Black And White Balls Moving");
myFrame.setVisible(true);
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}//end of class
The events triggered by the Timer are performed on the same event thread as the repaints. Calling repaint does not actively perform a paint event, rather it queues one for later. When you call your repaints from within the timer event, they will only get executed once the timer event is completed.
What you need to do is refactor your loop so that only a single swap is performed each time the timer triggers. I've done this for you as an example:
public class DrawPanel extends JPanel implements ActionListener {
public static final int NUMBER_OF_CIRCLES = 10;
Timer myTimer = new Timer(500, this);
int[] circles = new int[NUMBER_OF_CIRCLES];
public DrawPanel() {
arrayFill(circles);
if(NUMBER_OF_CIRCLES % 2 == 0) {
condition = circles.length/2 -1;
} else {
condition = circles.length/2;
}
i = circles.length - 1;
k = 1;
myTimer.start();
}
int i, j, k;
int condition;
boolean outer = true;
#Override
public void actionPerformed(ActionEvent e) {
if(outer) {
if(i > condition) {
j = i - k; // set j
outer = false; // and move to the inner loop swap
} else {
myTimer.stop(); // the outer loop is done so stop the timer
}
}
if(!outer) {
int tmp = circles[j];
circles[j] = circles[j+1];
circles[j+1] = tmp;
repaint();
j++;
if(j >= i) {
i--;
k++;
outer = true; // move to the outer condition
} // next time the timer triggers
}
}
#Override
protected void paintComponent(Graphics g) {
int x = 0;
int length = 40;
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Ellipse2D circle;
for(int index = 0; index<10; index++) {
if(circles[index] == 0){
circle = new Ellipse2D.Double(x, 120, length, length);
g2.draw(circle);
} else if(circles[index] == 1){
circle = new Ellipse2D.Double(x, 120, length, length);
g2.fill(circle);
}
x += 45;
}
//myTimer.start();
}
public static void arrayFill(int[] array) {
for(int i = 0; i<array.length; i++) {
if( i%2 == 0) {
array[i] = 0;
} else {
array[i] = 1;
}
}
}
}
(I'm sure it could be factored another way.)
Also:
I added #Override annotations which you should use. Doing so will warn you when you make certain mistakes. (Like misspelling a method name or incorrectly declaring its signature.)
I moved circles to an instance variable because I don't see a reason it should be static. It is part of the state of the DrawPanel instance.
I created a constructor which initializes variables such as circles.
paintComponent is a protected method and it should remain so unless there is a reason to promote it to public.
(I removed your comments and changed the bracing style just to condense the code for my answer.)
As a side note, you should read the tutorial Initial Threads. You are not creating your GUI on the Swing event thread. Basically you need to wrap your code in main inside a call to invokeLater:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
// create and show your GUI
}
});
}
The basic problem is in your actionPerformed method. Your two for loops are rearranging the array to its final arrangement very quickly. Each loop iteration will take a matter of nanoseconds to milliseconds to complete (it depends on how the repaint() method works). The entire process is finished in less than 50 milliseconds or so. That's too fast for your eyes to keep up.
Basically, the repaint() method is working, but it's working too fast for human eyes to keep up.
If you break up the for loops into something that does one step of the algorithm each time it's called, you can trigger that from a timer and see the animation at a human-detectable speed.
add a paint thread. it should always call repaint() like,
new Thread(){ // this can be started on main or constructor of object
public void run(){
while(true){
repaint();
try {
Thread.sleep(50);
} catch(Exception e){ }
}
}
}.start();
and then, on action performed, mark moving objects like movingObjects, keep a animate_x = 0 and keep a boolean variable like existAnimation
then on paintComponent, increase animate_x
animate_x = animate_x + 1;
if (animate_x >= MAX_WIDTH_OF_ANIMATION){
existAnimation = false;
}
and use this existAnimation, animate_x and movingObjects
like,
public void paintComponent(Graphics g)
{
int x = 0; //start point of circles;
int length = 40; //diagonal of the circles
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Ellipse2D circle;
//painting n circles based on the array
for(int index = 0; index<10; index++)
{
int paint_x = x;
if (movingObjects.has(circles[index])){
paint_x += animate_x;
}
if(circles[index] == 0){ //if the element of the arrayy is 0 then draw a void circle
circle = new Ellipse2D.Double(paint_x, 120, length, length);
g2.draw(circle);
}
else if(circles[index] == 1){ //if the element of the array is 1 them draw a filled circle
circle = new Ellipse2D.Double(paint_x, 120, length, length);
g2.fill(circle);
}
x += 45; //increas start pont of the next circle 45 pixles
}
myTimer.start();
}
Related
I'm currently having an issue where the image won't move when the y-value of the image is increasing. I wanted the image to move vertically so I made a method that controls the speed of the image, The parameter is the ActionEvent and the y-value for the player. The y-value increases as I printed out the value, but the image won't move. I've even added the timer which didn't make the image move at all. No error in the output whatsoever.
public void speedPerformed(ActionEvent e, Rectangle movingPlayer){
int speed = 15;
// help deals with gravity
ticks++;
// if the remainder of zero is given from tick
//then the object will feel heavier
if (ticks % 2 == 0 && yMotion < 15) {
yMotion += 3;
}
movingPlayer.y += yMotion;
}
#Override
public void actionPerformed(ActionEvent e) {
action.speedPerformed(e,movingPlayer);
gameInterface.getRenderer().repaint();
}
public void repaint(Graphics g) {
g.drawImage(Renderer.renderer.getImage(),movingPlayer.x,movingPlayer.y,100,100, null);
}
public RepaintConfiguration(GameInterface gameInterface) {
this.gameInterface = gameInterface;
lasers = new Lasers();
action = new Actions();
movingPlayer = new Rectangle(0, 550, 100, 100);
timer = new Timer(20,this);
timer.start();
}
let me know if you want to take a look at any of my codes that I haven't included here.
You code is wrong: you are updating the local variable y.
You should update directly the movingPlayer:
public void speedPerformed(ActionEvent e){
int speed = 15;
// help deals with gravity
ticks++;
// the y value of the moving player
// if the remainder of zero is given from tick
//then the object will feel heavier
if (ticks % 2 == 0 && yMotion < 15) {
yMotion += 3;
}
movingPlayer.y += yMotion;
}
Back again with another problem that has stumped me completely and cannot for the life of me fix.
So I had previously posted a question about my Java game I am making for a class that with the help of #MadProgrammer was fixed...mostly. Now there is a new problem that needs a post all to it's own
Previous Post:
Rows and columns with multidimensional array java
Problem:
In the code below I have it set up to loop through the variables x and y to make rows and columns on a jPanel. Each time it loops through it should randomly mark the "x,y" location with one of the "terrains" so that later it can "paint" that location with the appropriate colored 20x20 square.
The code runs great except for one thing, it looks like it skips the very first "if statement" that marks the "terran[0]" which is "floor". When the code is ran it "paints" the other three "terrains" and not a single "floor" "terrain".
I have looked for a solution on these posts but no success:
Java if statement is skipped
If statement being skipped during execution
Java - for loops being skipped
Java if-statement being skipped
Here is a working piece of code that results in the problem at hand:
import java.awt.*;
import javax.swing.*;
import java.util.*;
public class gamePanel extends JPanel
{
public gamePanel()
{
setBounds(115,93,480,480);
}
private Random generator = new Random();
int floor = 0; //initializes the variable floor to zero for later use
int dirt = 1;
int stone = 2;
int water = 3;
int width = 24;
int height = 24;
int x, y; // my x & y variables for coordinates
int[][] coords = new int[width][height]; //my array that I want to store the coordinates for later use in painting
int[] terrain = {floor, dirt, stone, water}; //my terrain that will determine the color of the paint
public void mapGen() //what should mark/generate the JPanel
{
for(x = 0; x < width; x++)
{
for(y = 0; y < height; y++)
{
int z = generator.nextInt(20);// part of the randomization
if(z <= 10)
{
coords[x][y] = terrain[0]; //should mark the coordinates as floor
}
if(z == 11)
{
coords[x][y] = terrain[3];//should mark the coordinates as water
}
if(z >= 12 && z <= 16)
{
coords[x][y] = terrain[2];//should mark the coordinates as stone
}
if(z >= 17 && z <= 19)
{
coords[x][y] = terrain[1];//should mark the coordinates as dirt
}
coords[0][0] = terrain[0]; // sets coordinate 0,0 to floor //need to have these always be floor
coords[23][23] = terrain[0]; // sets coordinate 24,24 to floor //^^^^^^^^^^
}
}
}
#Override
public void paintComponent(Graphics g)//what will paint each 20x20 square on the grid what it is assigned
{
super.paintComponent(g);
for(int x = 0; x < width; x++)
{
for(int y = 0; y < height; y++)
{
mapGen();
if(coords[x][y] == terrain[floor])//should paint the floor color at marked coordinates
{
g.setColor(Color.white);
g.fillRect((x*20), (y*20), 20, 20);
}
if(coords[x][y] == terrain[dirt]);//should paint the dirt color at marked coordinates
{
g.setColor(new Color(135,102,31));
g.fillRect((x*20), (y*20), 20, 20);
}
if(coords[x][y] == terrain[stone])//should paint the stone color at marked coordinates
{
g.setColor(new Color(196,196,196));
g.fillRect((x*20),(y*20),20,20);
}
if(coords[x][y] == terrain[water])//should paint the water color at marked coordinates
{
g.setColor(new Color(85,199,237));
g.fillRect((x*20),(y*20),20,20);
}
}
}
}//end paintComponent
public static void main(String[] args)
{
gamePanel panel = new gamePanel();
JFrame frame = new JFrame();
frame.setSize(500,550);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(panel);
frame.setVisible(true);
}//end main
}// end gamePanel
Please keep in mind that I am a novice programmer and I am still learning. So anything that is not considered "basic" code please explain in detail.
I am working on science research and am getting strange results from my code, and as a visual learner I thought it efficient to print my data to screen as it is analysed to try and see where the code is going wrong. For reference, I am analyzing a nonlinear waveform.
Here is the code for analysis:
public void getMachineCode(int trial, int wave){
double[] tempwave = new double[5000];
int index = 0;
for(int x = 0; x < 5000; x++){
tempwave[x] = waves[trial][wave][x];
}
for(int repeat = 5; repeat > 0; repeat--){
int tempstart = index;
if(tempwave[index] > 0){
while(tempwave[index] > 0){
index++;
}
}else{
while(tempwave[index] < 0){
index++;
}
}
int midwave = index - tempstart;
if(tempwave[midwave] > 0){
System.out.println(0);
}else{
System.out.println(1);
}
}
}
Here, all I want is to print the (x,y) coordinates of my trial to the screen as the index increases so it is a constantly changing graph, something like:
if(tempwave[index] > 0){
while(tempwave[index] > 0){
index++;
printpixel(index,y); //something to show where the code is scanning
}
}else{
while(tempwave[index] < 0){
index++;
printpixel(index,y);
}
I am not very familiar with java graphics and was looking into using a JFrame but it is hard for me to implement. There will be about 4000 data points to plot, so I might also have to only print every few points or is there a way to make a better visual? Any ideas? Thanks!
This should give you basic idea.
Normally with Swing graphics, you override the paintComponent() method and draw from some shared state
Instead you can just draw to a large image, and then draw that image using paintComponent()
I've compressed this into a single self contained example, this can be separated out in a larger application
Example
public static void main(String[] args) throws Exception {
final BufferedImage image = new BufferedImage(1280, 768,
BufferedImage.TYPE_INT_RGB);
JPanel canvas = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
};
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout()); // <== make panel fill frame
frame.add(canvas, BorderLayout.CENTER);
frame.setSize(500, 500);
frame.setVisible(true);
// do you drawing somewhere else, maybe a different thread
Graphics g = image.getGraphics();
g.setColor(Color.red);
for (int x = 0; x < 100; x += 5) {
for (int y = 0; y < 100; y += 5) {
g.drawRect(x, y, 1, 1);
}
}
g.dispose();
canvas.repaint();
}
So I followed a free manual instructing how to write Asteroids in Java, and it runs great. I would like to add it into a program so I can call it, run it for a time, and then have it return an int. The program I'm making is an application, and I've been searching for a while trying and failing, figuring out how to make make it run as an application. The stuff I've read here says I should do this:
public class Main extends JFrame {
public static void main(String[] args) {
AsteroidsGame game = new AsteroidsGame();
JFrame frame = new JFrame();
frame.setLayout(new GridLayout (1,1));
frame.add(game);
frame.setSize(500,500);
game.init();
game.start();
frame.setVisible(true);
}
}
But then I get an error
Exception in thread "main" java.lang.NullPointerException
at AsteroidsGame.init(AsteroidsGame.java:49)
at Main.main(Main.java:15)
which points me to the below for line 49, and my game.init() for line 15.
g = img.getGraphics();
Here's the code for the AsteroidsGame, I'm too tired to think anymore. I just need to get it to run as an application, any other code changes are irrelevant at this point. I know it's a lot of code but I'm hoping it's a simple something I've missed. Any help is greatly appreciated. Thank you!
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
public class AsteroidsGame extends Applet implements Runnable, KeyListener {
Thread thread;
Dimension dim;
Image img;
Graphics g;
long endTime, startTime, framePeriod;
Ship ship;
boolean paused; // True if the game is paused. Enter is the pause key
Shot[] shots;
int numShots;
boolean shooting;
Asteroid[] asteroids; // the array of asteroids
int numAsteroids; // the number of asteroids currently in the array
double astRadius, minAstVel, maxAstVel; // values used to create
// asteroids
int astNumHits, astNumSplit;
int level; // the current level number
int money;
double fuel;
Random rand = new Random();
public void init() {
resize(500, 500);
shots = new Shot[41]; // 41 is a shot's life period plus one.
// since at most one shot can be fired per frame,
// there will never be more than 41 shots if each one only
// lives for 40 frames.
numAsteroids = 0;
level = rand.nextInt(25)+1; // will be incremented to 1 when first level is set up
astRadius = 10; // values used to create the asteroids
minAstVel = 2;
maxAstVel = 8;
astNumHits = 3;
astNumSplit = 2;
money = 0;
fuel = 100;
endTime = 0;
startTime = 0;
framePeriod = 25;
addKeyListener(this); // tell it to listen for KeyEvents
dim = getSize();
img = createImage(dim.width, dim.height);
g = img.getGraphics();
thread = new Thread(this);
thread.start();
}
public void setUpNextLevel() { // start new level with one more asteroid
level++;
// create a new, inactive ship centered on the screen
// I like .35 for acceleration, .98 for velocityDecay, and
// .1 for rotationalSpeed. They give the controls a nice feel.
ship = new Ship(250, 250, 0, .35, .98, .1, 12);
numShots = 0; // no shots on the screen at beginning of level
paused = false;
shooting = false;
// create an array large enough to hold the biggest number
// of asteroids possible on this level (plus one because
// the split asteroids are created first, then the original
// one is deleted). The level number is equal to the
// number of asteroids at it's start.
asteroids = new Asteroid[level
* (int) Math.pow(astNumSplit, astNumHits - 1) + 1];
numAsteroids = level;
// create asteroids in random spots on the screen
for (int i = 0; i < numAsteroids; i++)
asteroids[i] = new Asteroid(Math.random() * dim.width,
Math.random() * dim.height, astRadius, minAstVel,
maxAstVel, astNumHits, astNumSplit);
}
public void paint(Graphics gfx) {
g.setColor(Color.black);
g.fillRect(0, 0, 500, 500);
for (int i = 0; i < numShots; i++)
// draw all the shots on the screen
shots[i].draw(g);
for (int i = 0; i < numAsteroids; i++)
asteroids[i].draw(g);
ship.draw(g); // draw the ship
g.setColor(Color.cyan); // Display level number in top left corner
g.drawString("Level " + level, 20, 20);
g.drawString("Money " + money, 80, 20);
g.drawString("Fuel " + fuel, 20, 50);
gfx.drawImage(img, 0, 0, this);
}
public void update(Graphics gfx) {
paint(gfx);
}
public void run() {
for (;;) {
startTime = System.currentTimeMillis();
// start next level when all asteroids are destroyed
if (numAsteroids <= 0)
setUpNextLevel();
if (!paused) {
ship.move(dim.width, dim.height); // move the ship
// move shots and remove dead shots
for (int i = 0; i < numShots; i++) {
shots[i].move(dim.width, dim.height);
// removes shot if it has gone for too long
// without hitting anything
if (shots[i].getLifeLeft() <= 0) {
// shifts all the next shots up one
// space in the array
deleteShot(i);
i--; // move the outer loop back one so
// the shot shifted up is not skipped
}
}
if(ship.accelerating && fuel>0){
fuel -= 1.5;
}
if(ship.accelerating && fuel == 0)
{
ship.accelerating = false;
}
// move asteroids and check for collisions
updateAsteroids();
if (shooting && ship.canShoot()) {
// add a shot on to the array
shots[numShots] = ship.shoot();
numShots++;
}
}
repaint();
try {
endTime = System.currentTimeMillis();
if (framePeriod - (endTime - startTime) > 0)
Thread.sleep(framePeriod - (endTime - startTime));
} catch (InterruptedException e) {
}
}
}
private void deleteShot(int index) {
// delete shot and move all shots after it up in the array
numShots--;
for (int i = index; i < numShots; i++)
shots[i] = shots[i + 1];
shots[numShots] = null;
}
private void deleteAsteroid(int index) {
// delete asteroid and shift ones after it up in the array
numAsteroids--;
for (int i = index; i < numAsteroids; i++)
asteroids[i] = asteroids[i + 1];
asteroids[numAsteroids] = null;
}
private void addAsteroid(Asteroid ast) {
// adds the asteroid passed in to the end of the array
asteroids[numAsteroids] = ast;
numAsteroids++;
}
private void updateAsteroids() {
for (int i = 0; i < numAsteroids; i++) {
// move each asteroid
asteroids[i].move(dim.width, dim.height);
// check for collisions with the ship, restart the
// level if the ship gets hit
if (asteroids[i].shipCollision(ship)) {
money+= Math.random()*1000;
deleteAsteroid(i);
//level--; // restart this level
//numAsteroids = 0;
return;
}
// check for collisions with any of the shots
for (int j = 0; j < numShots; j++) {
if (asteroids[i].shotCollision(shots[j])) {
// if the shot hit an asteroid, delete the shot
deleteShot(j);
// split the asteroid up if needed
if (asteroids[i].getHitsLeft() > 1) {
for (int k = 0; k < asteroids[i].getNumSplit(); k++)
addAsteroid(asteroids[i].createSplitAsteroid(
minAstVel, maxAstVel));
}
// delete the original asteroid
deleteAsteroid(i);
j = numShots; // break out of inner loop - it has
// already been hit, don't need to check
// for collision with other shots
i--; // don't skip asteroid shifted back into
// the deleted asteroid's position
}
}
}
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
// These first two lines allow the asteroids to move
// while the player chooses when to enter the game.
// This happens when the player is starting a new life.
if (!ship.isActive() && !paused)
ship.setActive(true);
else {
paused = !paused; // enter is the pause button
if (paused) // grays out the ship if paused
ship.setActive(false);
else
ship.setActive(true);
}
} else if (paused || !ship.isActive()) // if the game is
return; // paused or ship is inactive, do not respond
// to the controls except for enter to unpause
else if (e.getKeyCode() == KeyEvent.VK_UP)
{if(fuel>0){
ship.setAccelerating(true);
//fuel -= 1.5;
}
else{
fuel = 0;
}
}
else if (e.getKeyCode() == KeyEvent.VK_LEFT)
{
ship.setTurningLeft(true);
}
else if (e.getKeyCode() == KeyEvent.VK_RIGHT)
ship.setTurningRight(true);
//else if (e.getKeyCode() == KeyEvent.VK_CONTROL)
//shooting = true; // Start shooting if ctrl is pushed
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_UP)
ship.setAccelerating(false);
else if (e.getKeyCode() == KeyEvent.VK_LEFT)
ship.setTurningLeft(false);
else if (e.getKeyCode() == KeyEvent.VK_RIGHT)
ship.setTurningRight(false);
//else if (e.getKeyCode() == KeyEvent.VK_CONTROL)
//shooting = false;
}
public void keyTyped(KeyEvent e) {
}
}
I believe that createImage() is going to return null until the component is actually on-screen, wihch i believe is after the thread has started.
Instead of this:
img = createImage(dim.width, dim.height);
g = img.getGraphics();
thread = new Thread(this);
thread.start();
try:
new Thread(new Runnable() {
public void run() {
do {
try {
Thread.sleep(25);
} catch(InterruptedException e) {
System.out.println("wait interrupted");
break;
}
} while(!isDisplayable());
// Now it should be safe to make these calls.
img= createImage(dim.width, dim.height);
g = img.getGraphics();
start();
}
}).start();
I am trying to paint circles onto my panel but the colour of the circle is determined by some parameters. Firstly the circles should be painted as white then go into a for loop checking which paramater matches and should paint the circle in that colour. the location of the circles are stored in an array. my code i have done so far does not work. i am clearly doing something wrong but i am new to java and coding so i am very stuck. if someone could show me how to edit/change my code i would really appreciate it. ArrayList circlesT is an arraylist of the circles locations and temp is the array with values i have the parameters too.
public void paintComponent(Graphics g) {
drawShapes(g, circlesT);
}
public void drawShapes(Graphics g, final ArrayList<Shape> circlesT) {
final Graphics2D ga = (Graphics2D) g;
ga.drawImage(newImage, 0, 0, null);
for (int i = 0; i < circlesT.size(); i++) {
ga.draw(circlesT.get(i));
ga.setPaint(Color.white);
ga.fill(circlesT.get(i));
}
Timer timer = new Timer();
TimerTask t;
t = new TimerTask() {
#Override
public void run() {
for (int i = 0; i < 10; i++) {
if (read.temp.get(i) < 31 && read.temp.get(i) > 30) {
ga.draw(circlesT.get(i));
ga.setPaint(Color.green);
ga.fill(circlesT.get(i));
} else if (read.temp.get(i) < 32 && read.temp.get(i) > 31) {
ga.draw(circlesT.get(i));
ga.setPaint(Color.red);
ga.fill(circlesT.get(i));
} else if (read.temp.get(i) < 33 && read.temp.get(i) > 32) {
ga.draw(circlesT.get(i));
ga.setPaint(Color.yellow);
ga.fill(circlesT.get(i));
}
}
}
};
//repaint();
timer.schedule(t, 0, 1000);
}
A few points.
You shouldn't keep hold of the Graphics object from paintComponent beyond the end of the method invocation.
In general you should use javax.swing.Timer instead of java.util.Timer.
What you should actually be doing in the timer task/action is to update the state of your data and call repaint.
The code doing all the painting should be called in paintComponent before it returns.