How to update jlabel while running animation? - java

I have a little animation where a rectangle, which is a jlabel with blue background, is constantly moving down the screen. I am running a thread to do this.
Now, i want to have another jlabel where it shows the current position of the rectangle.
public void run()
{
Pnl.requestFocus();
x = (int) p.getX(); //find location of rectangle
y = (int) p.getY();
while (y < 450)
{
RectangleLabel.setLocation(x, y); //reset location of the rectangle
y += 10;
try {
Thread.sleep(100);
}
catch (InterruptedException e)
{
}
}
}
Now i want to insert this code inside the while statement.
locationLabel.setText(String.valueOf(450-y));
But every time i do, the jlable updates but the rectangle doesnt move anymore.
How would i go about?

Try This :
Run This example
import javax.swing.*;
import java.lang.*;
class TestThread extends JFrame implements Runnable{
JLabel RectangleLabel,locationLabel;
int x,y=0;
TestThread()
{
setVisible(true);
setLayout(null);
RectangleLabel=new JLabel("Rectangle");
RectangleLabel.setBounds(10,10,100,100);
locationLabel=new JLabel();
locationLabel.setBounds(200,200,100,100);
add(RectangleLabel);
add(locationLabel);
setSize(1000,1000);
Thread t=new Thread(this);
t.run();
}
public void run()
{
while (y < 450)
{
RectangleLabel.setLocation(x, y); //reset location of the rectangle
y += 10;
locationLabel.setText(""+y);
try {
Thread.sleep(100);
}
catch (InterruptedException e)
{
}
if(y==440)
{
y=0;
}
}
}
public static void main(String args[]) {
TestThread t=new TestThread();
}
}

Related

Repaint() working only half times

i've got a problem with what should be a simple excercise.
I've been asked to make an applet that prints a green oval (filled) that becomes larger until it hits the borders, than start becoming smaller.
This should go on until you close the applet.
Well, i came out with this code
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JApplet;
public class Disco extends JApplet{
private int x;
private int y;
private int r;
private boolean enlarge;
MakeLarger makeLarger;
MakeSmaller makeSmaller;
public void init() {}
public void start() {
x = getWidth()/2;
y = getHeight()/2;
r = 50;
enlarge = true;
makeLarger = new MakeLarger();
makeLarger.start();
}
public void paint(Graphics g) {
g.setColor(Color.GREEN);
g.fillOval(x - r, y- r, r*2, r*2);
}
public void update() {
if(enlarge) {
makeLarger = new MakeLarger();
makeLarger.start();
} else {
makeSmaller = new MakeSmaller();
makeSmaller.start();
}
}
private class MakeLarger extends Thread {
public void run() {
while(true) {
x = getWidth()/2;
y = getHeight()/2;
if(getWidth() > getHeight()) {
if(r < getHeight()/2) {
r++;
repaint();
try {
sleep(25);
} catch(InterruptedException e) {
e.printStackTrace();
}
} else {
enlarge = false;
update();
Thread.currentThread().interrupt();
return;
}
} else {
if(r < getWidth()/2) {
r++;
repaint();
try {
sleep(25);
} catch(InterruptedException e) {
e.printStackTrace();
}
} else {
enlarge = false;
update();
Thread.currentThread().interrupt();
return;
}
}
}
}
}
private class MakeSmaller extends Thread {
public void run() {
while(true) {
x = getWidth()/2;
y = getHeight()/2;
if(r > 50) {
r--;
repaint();
revalidate();
try {
sleep(25);
} catch(InterruptedException e) {
e.printStackTrace();
}
} else {
enlarge = true;
update();
Thread.currentThread().interrupt();
return;
}
}
}
}
}
When I start my applet the oval start growing correctly until it hits the border and then suddently stop.
The first thing i thought was that it wasn't getting smaller correctly. But a little System.out.println work showed me that all computation was going on correctly, the problem is that the applet repaint only while the makeLarger thread is active, when the makeSmaller thread is at work the call to repaint() doesn't work!
If i resize the applet window while the makeSmaller Thread is at work it repaints correctly showing me the oval getting smaller.
Can, please, someone enlight me on this odd behavior?
What am I missing?
thank you everyone for your most appreciated help and sorry if my english is so poor!
I can't say that I've looked at all the code, but a couple of suggestions:
Paint in a JPanel's paintComponent override.
This is key: call the super.paintComponent method in the override, first line. This gets rid of prior images so that the image can get smaller.
Display the JPanel within your JApplet by adding it to the applet.
Myself, I'd use a single Swing Timer for the animation loop, and would use a boolean to decide which direction the sizing should go.
But regardless of whether I were using a Swing Timer or a Runnable placed in a Thread, I'd try to keep things a simple as possible, and that would mean using a single Timer that changes direction of resizing or a single Runnable/Thread that changes size of resizing based on a boolean. This swapping of threads that you're doing just serves to overly and unnecessarily complicate things, and could quite possibly be the source of your error.
As a side recommendation, you almost never want to extend Thread. Much better is to create classes that implement Runnable, and then when you need to run them in a background thread, create a Thread, passing in your Runnable into the Thread's constructor, and then calling start() on the Thread.
First things first, thank you all for helping me!
The problem I was trying to solve was this:
Make an applet which shows a green oval getting larger until it hits the borders, then it should start getting smaller up to a fixed radius (50), then it should start over (and over) again. Solve the problem by making two threads (by extending Thread).
Just to explain why the algorithm was so odd!
Well, reading your suggestions I fixed my code, now it's running properly. Here is the code if anyone will need this.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.JApplet;
import javax.swing.Timer;
public class Disco extends JApplet{
private int x;
private int y;
private int r;
private boolean enlarge;
MakeLarger makeLarger;
MakeSmaller makeSmaller;
public void init() {}
public void start() {
x = getWidth()/2;
y = getHeight()/2;
r = 50;
enlarge = true;
makeLarger = new MakeLarger();
makeLarger.start();
Timer timer = new Timer(1000/60, new ActionListener() {
public void actionPerformed(ActionEvent e) {
repaint();
}
});
timer.start();
}
public void paint(Graphics g) {
BufferedImage offScreenImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_4BYTE_ABGR_PRE);
Graphics2D g2D = (Graphics2D) offScreenImage.getGraphics();
g2D.clearRect(0, 0, getWidth(), getHeight());
g2D.setColor(Color.GREEN);
g2D.fillOval(x - r, y- r, r*2, r*2);
g.drawImage(offScreenImage, 0, 0, this);
}
public void update() {
if(enlarge) {
makeLarger = new MakeLarger();
makeLarger.start();
} else {
makeSmaller = new MakeSmaller();
makeSmaller.start();
}
}
private class MakeLarger extends Thread {
public void run() {
while(true) {
x = getWidth()/2;
y = getHeight()/2;
if(getWidth() > getHeight()) {
if(r < getHeight()/2) {
r++;
try {
sleep(25);
} catch(InterruptedException e) {
e.printStackTrace();
}
} else {
enlarge = false;
update();
Thread.currentThread().interrupt();
return;
}
} else {
if(r < getWidth()/2) {
r++;
try {
sleep(25);
} catch(InterruptedException e) {
e.printStackTrace();
}
} else {
enlarge = false;
update();
Thread.currentThread().interrupt();
return;
}
}
}
}
}
private class MakeSmaller extends Thread {
public void run() {
while(true) {
x = getWidth()/2;
y = getHeight()/2;
if(r > 50) {
r--;
try {
sleep(25);
} catch(InterruptedException e) {
e.printStackTrace();
}
} else {
enlarge = true;
update();
Thread.currentThread().interrupt();
return;
}
}
}
}
}

java simple animation with threads

I'm looking to create a simple 2D animation using a thread. Once the thread is launched, i'm having trouble figuring out exactly what to put in the run method. Right now, the objects of the Particle class are painted on the frame but there's no animation. Also i could use your help with how to close the thread when the user closes the frame
public class ParticleFieldWithThread extends JPanel implements Runnable{
private ArrayList<Particle> particle = new ArrayList<Particle>();
boolean runnable;
public ParticleFieldWithThread (){
this.setPreferredSize(new Dimension(500,500));
for(int i = 0; i < 100; i++) {
particle.add(new Particle());
}
Thread t1 = new Thread();
t1.start();
}
public void run () {
while (true ) {
try {
Thread.sleep(40);
for (Particle p : particle) {
p.move();
}
repaint();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setColor(Color.RED);
for (Particle p : particle) {
g2.fill(new Rectangle2D.Double(p.getX(), p.getY(), 3, 3));
}
}
public static void main(String[] args) {
final JFrame f = new JFrame("ParticleField");
final ParticleFieldWithThread bb = new ParticleFieldWithThread();
f.setLayout(new FlowLayout());
f.add(bb);
f.pack();
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Here's the particle class
public class Particle {
private double x , y ;
Random r = new Random();
public Particle () {
x = r.nextDouble()*500;
y = r.nextDouble()*500;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public void move() {
x += r.nextBoolean() ? 1 : - 1;
y += r.nextBoolean() ? 1 : - 1;
//System.out.println("x : " + x+" y: " + y);
}
}
This does nothing of use:
Thread t1 = new Thread();
t1.start();
You need to pass a Runnable (in your code, it would be the current object of the class, the this) into the Thread's constructor for it to have any meaning or function. i.e.,
Thread t1 = new Thread(this);
t1.start();
For my money, I'd do something completely different and would use a Swing Timer for simple Swing animation.

How to put two different tasks in Threads

I have following code. in this code i have an image which moves from left to right and a button which has an event. but i want to put these both tasks in Threads. so that it can work properly. the problem with this code is that button event does not work until it reaches to the right most point.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class MyImage extends JFrame implements ActionListener
{
static int xPixel = 20;
Image myImage, offScreenImage;
Graphics offScreenGraphics;
JPanel p = new JPanel();
Button btn = new Button("bun");
JFrame f = new JFrame();
public MyImage()
{
myImage = Toolkit.getDefaultToolkit().getImage("mywineshoplogo.jpg");
setExtendedState(JFrame.MAXIMIZED_BOTH);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
add(p);
p.add(btn);
moveImage();
btn.addActionListener(this);
}
public void update(Graphics g)
{
paint(g);
}
public void paint(Graphics g)
{
int width = getWidth();
int height = getHeight();
if (offScreenImage == null)
{
offScreenImage = createImage(width, height);
offScreenGraphics = offScreenImage.getGraphics();
}
// clear the off screen image
offScreenGraphics.clearRect(0, 0, width + 1, height + 1);
// draw your image off screen
offScreenGraphics.drawImage(myImage, xPixel, 10, this);
// draw your image off screen
// show the off screen image
g.drawImage(offScreenImage, 0, 0, this);
// show the off screen image
}
void moveImage() //left to right move
{
Thread hilo = new Thread() {
public void run() {
try {
for (int i = 0; i < 530; i++)
{
xPixel += 1;
repaint();
// then sleep for a bit for your animation
try
{
Thread.sleep(4);
} /* this will pause for 50 milliseconds */
catch (InterruptedException e)
{
System.err.println("sleep exception");
}
}
} //try
catch (Exception ex) {
// do something...
}
}
};
hilo.start();
}
/* void moveimg() // right to left move
{
for (int i = 529; i > 0; i--)
{
if (i == 1)
{
moveImage();
}
xPixel -= 1;
repaint();
// then sleep for a bit for your animation
try
{
Thread.sleep(40);
} // this will pause for 50 milliseconds
catch (InterruptedException e)
{
System.err.println("sleep exception");
}
}
} */
public void actionPerformed(ActionEvent ae)
{
try
{
if (ae.getSource() == btn)
{
p.setBackground(Color.RED);
}
}
catch (Exception e)
{
System.out.println("error");
}
}
public static void main(String args[])
{
MyImage me = new MyImage();
}
}
Whenever you are about to write Thread.sleep in your GUI code, stop yourself and introduce a task scheduled on Swing's Timer. This is exactly what you need with your code: schedule each update as a separate scheduled task on Timer. Timer is quite simple and straightforward to use, see for example this official Oracle tutorial.

How to use robot class

I have a sort of animation going on in which a rectangle is increasing and decreasing in size........what i want to do here is detect the color of a particular location through Robot() class but its not happening..........why?? I also want to know if Robot() can be used outside try or without main() class.
//<applet code=ctry.java width=500 height=500></applet>
import java.awt.*;
import java.applet.Applet;
import java.awt.AWTException;
public class ctry extends Applet implements Runnable{
Thread d=null;
int l=0,t=0,i=250,j=250;
Color color=null;
public void init(){
setBackground(Color.red);
}
public void start(){
d=new Thread(this);
d.start();
}
public void run(){
System.out.println("in run");
try{
Robot robo=new Robot();
System.out.println("after robo");
while(true){
System.out.println("in while");
repaint();
color=robo.getPixelColor(i,j);
System.out.println("Red = " + color.getRed());
l+=10;
t+=10;
d.sleep(100);
if(t>=225)
{t=0;}
if(l>=225)
{l=0;}
}
}
catch(Exception e)
{}
}
public void paint(Graphics g)
{
System.out.println("in paint");
g.setColor(Color.blue);
g.fill3DRect(225,225,l*2,t*2,true);
}
public void destroy()
{}
}
You could try to capture an image instead and check the color there. The Robot.getPixelColor() is very slow, it returns a new Color instance every time. Try using a BufferedImage instead:
Color color = Color.black;
int screenWidth = 768;
int screenHeight = 1024;
Rectangle rectangle = new Rectangle(screenWidth, screenHeight);
BufferedImage image = robot.createScreenCapture(rectangle);
for (int y = 0 ; y < screenHeight ; y++) {
for (int x = 0 ; x < screenWidth ; x++) {
if(image.getRGB(x, y) == color.getRGB()) {
return true;
}
}
}
And yes, you can use the Robot everywhere and you can deal with the exceptions, but most on them are runtime exceptions, so you don't have to.

How to get the color of a pixel

In my code below....i wish to add a yellow bar at the bottom if upon firing a bullet, the bullet reaches the moving bar at the top(which is a trail of alternative yellow and cyan boxes) and touches it at a yellow box.For that what I am planning is to first detect the color of the pixel where the bullet touches the moving bar and then add yellow bar below if the pixel color was yellow............Here is my code:
//
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
public class abyss extends Applet implements Runnable,KeyListener{
int lim=446,l,src,i=-40,n,c,ct=450,cl=225,y,f,bl,bw,fr,mud=0;
Thread v=null;
public void init() {
setBackground(Color.black);
addKeyListener(this);
}
public void start() {
v=new Thread(this);
v.start();
}
public void run() {
try {
int trainDelay = 0;
while (true) {
if(ct<=200)
{repaint();
}
if (y == 1) {
if (f<=41) {
bl = cl + 25;
bw = 10;
f = lim;
}
if (f > 41) {
repaint(bl, f, bw, bw + 1);
if (--f<=41) {
if(l%80==0)
{mud=1;
ct=ct-20;
System.out.println("decreased");
lim=lim-20;
repaint();}
else if(l%80!=0 && (ct+20<=420))
{ct=ct+20;
lim=lim+20;
}
y = 0;
bw = 0;
}
}
}
if (trainDelay <= 0) {
repaint();
i = i + 40;
c = 1;
n = i / 40;
trainDelay = 200;
}
Thread.sleep(5);
trainDelay--;
}
} catch (Exception e) {
}
}
public void paint(Graphics g) {
if(ct>=200){
if(mud==1)
{g.setColor(Color.orange);
g.fill3DRect(0,ct+20,500,450-ct,true);}
g.setColor(Color.darkGray);
g.fill3DRect(0,200,30,300,true);
g.fill3DRect(470,200,30,300,true);
g.fill3DRect(0,470,500,30,true);
g.setColor(Color.blue);
g.fill3DRect(cl,ct,50,20,true);
setBackground(Color.black);
for(int j=n-1;j>=0;j--)
{ l=j*40;
if((c%2)==0)
{g.setColor(Color.cyan);
g.fill3DRect(l,0,50,40,true);}
else
{g.setColor(Color.orange);
g.fill3DRect(l,0,50,40,true);}
c++;
}
}
{g.setColor(Color.yellow);
g.fillOval(bl,f,bw,bw);
if(ct<=200)
{setBackground(Color.red);
g.setColor(Color.yellow);
g.drawString("You win!!",215,210);
}
} }
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_LEFT && cl>=38){
cl=cl-10;}
if(e.getKeyCode()==KeyEvent.VK_RIGHT && cl<=412){
cl=cl+10;}
if(e.getKeyCode()==KeyEvent.VK_UP){
y=1;}
}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
public void stop() {
try{wait();}
catch(Exception e) {}
}
public void destroy() {}
}
Please tell me how to detect the color.........can getColor() be used??
It looks like you are off to a good start.
I would recommend that you have your cyan and yellow boxes be objects with a color and location attributes.
Create a getColor method for your box objects, and create a getLocation method for your box objects and bullet object.
when bullet.getLocation = box.getLocation
then box.getColor
Take a look at this Java/Processing App that sets the color of a circle when clicked on. It uses principles similar to what I just described.
https://sourceforge.net/projects/all-spark-cube/
https://github.com/spudstud/All-Spark-Cube/blob/master/Sandbox/Panel_2d/LedObject.pde

Categories

Resources