3 Replies - 2515 Views - Last Post: 24 February 2009 - 07:04 PM Rate Topic: -----

#1 onorinbejasus  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 156
  • Joined: 22-February 09

Using Graphics in a thread

Posted 24 February 2009 - 02:55 PM

I posted a similar question a couple days ago, yet I still cannot find the solution. I am animating a snowman's arms using threads; one thread for each arm. In my thread classes, I have a constructor that accepts the Graphics parameter from my main class. The problem is that the snowman will load, but the arm will not appear at all. I am sure the code is being run because I put checks at different points of the thread. These checks appear, but the arms do not. Here is my main code and threads... can someone please help?

 
import javax.swing.JApplet;
	import java.awt.Graphics;

 
	
	public class Snow extends JApplet {


		public void paint (Graphics canvas) {
			
			
			// variables
			int eyeY = 50; 
			int eyeHeight = 7;
			int eyeWidth = 10;
			int buttonHeight = 7;
			
							
			// The head of the snowman
			
			canvas.drawOval(65,35,60,50); // head
			canvas.fillRect(69,35,50,10); // brim of had
			canvas.fillRect(80, 15, 28, 20); // bucket of hat
				 
			
			// the face
			
			canvas.fillOval(78,eyeY,eyeWidth,eyeHeight); // left eye
			canvas.fillOval(100,eyeY,eyeWidth,eyeHeight); // right eye
			canvas.fillOval(90,60,buttonHeight,buttonHeight); // nose
			canvas.drawArc(78,67,32,10,180,180);
			
			// the body 
			
			canvas.drawOval(57,86,78,65); // second snowball
			canvas.fillOval(90,95,10,buttonHeight); // 1st button
			canvas.fillOval(90, 110, 10, buttonHeight); // 2nd button
			canvas.fillOval(90,125,10,buttonHeight); // 3rd button
			canvas.drawOval(52,150,90,65); // last snowball
			
			// arms
			
			Leftarm la;
			la = new Leftarm(canvas);
			System.out.println("start LA");
			la.start();
			System.out.println("start RA");
			RightArm ra;
			ra = new RightArm(canvas);
			ra.start();
			System.out.println("Both arms started\n"+canvas);
		}
		}



import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;

 class RightArm extends Thread{
	 private Graphics canvas;
	 public RightArm(Graphics canvas) {
		   
		 this.canvas = canvas;	
			
			}

		public void run() {
			
			Random generator = new Random();
			int flag =0;
			
			int random = generator.nextInt(150);
			
			int x = 110;
			canvas.drawLine(134,110,170,x);
		
			do
				{
				
				
				
				if (x >= random)
				{
					x = minus(random,canvas,x);
					flag++;
					
				}else
				
				{
			
					x = plus(random,canvas,x);
					flag++;
				 
				}
				
				random = generator.nextInt(150);
			
				}while (flag != 1000);
			}

		private int minus(int random,Graphics canvas,int count) {
			
			for (int x = count; x>=random; x--)
				{
				canvas.setColor(Color.black);
				canvas.drawLine(134,110,170,x); 
				try{Thread.sleep(10);}catch(Exception e){};
				canvas.setColor(Color.white);
				canvas.drawLine(134,110,170,x);
				
				if (x== 50)
				{
					canvas.setColor(Color.black);
					canvas.drawLine(134,110,170,x); 
					random = 50;
					break;
				}
				
				}
			
			
			return random;
			
		}
		
private int plus(int random, Graphics canvas,int count) {
			
			for (int x = count; x<=random; x++)
			{
				canvas.setColor(Color.black);
				canvas.drawLine(134,110,170,x); 
				try{Thread.sleep(10);}catch(Exception e){};
				canvas.setColor(Color.white);
				canvas.drawLine(134,110,170,x);
				
			}
			
			 
			return random;
			
			}
 }



import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;


	class Leftarm extends Thread {
			private Graphics canvas;
	
			public Leftarm(Graphics canvas) {
		
				this.canvas=canvas;
		
		}

	public void run() {
		
		Random generator = new Random();
		int flag =0;
		
		int random = generator.nextInt(150);
		
		int x = 110;
		canvas.drawLine(20,x,57,110);
		System.out.println("running LA");
		
		do
			{
			
			
			
			if (x >= random)
			{
				x = minus(random,x);
				flag++;
				
			}else
			
			{
		
				x = plus(random,x);
				flag++;
			 
			}
			
			random = generator.nextInt(150);
		
			}while (flag != 1000);	
		}

	private int minus(int random,int count) {
		System.out.println("up "+random+" " + canvas);
		for (int x = count; x>=random; x--)
			{
			canvas.setColor(Color.blue);
			canvas.drawLine(20,x,57,110);
			System.out.print('.');
			try{Thread.sleep(10);}catch(Exception e){};
			canvas.setColor(Color.white);
			canvas.drawLine(20,x,57,110);
			
			if (x== 50)
			{
				canvas.setColor(Color.black);
				canvas.drawLine(20,x,57,110); 
				random = 50;
				break;
			}
			
			}
		
		
		return random;
		
	}
private int plus(int random, int count) {
		System.out.println("down");
		for (int x = count; x<=random; x++)
		{
			canvas.setColor(Color.black);
			canvas.drawLine(20,x,57,110); 
			try{Thread.sleep(10);}catch(Exception e){};
			canvas.setColor(Color.white);
			canvas.drawLine(20,x,57,110);
			
		}
		
		 
		return random;
		
		}
	}




One idea that I had was that while the threads were running parallel to one another, the changing of color to white may overlap can cause the color to be white the whole time.

Is This A Good Question/Topic? 0
  • +

Replies To: Using Graphics in a thread

#2 LaFayette  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 43
  • View blog
  • Posts: 326
  • Joined: 24-November 08

Re: Using Graphics in a thread

Posted 24 February 2009 - 03:19 PM

I can't check or compile your code, but usually it isnt safe to use swing together with threads in the normal way.

But try putting something like this in your run() methods
Runnable runner = new Runnable() {
     public void run() {
         some_function();
     }
 };

 SwingUtilities.invokeLater(runner);



and let some_function() be where you do ALL drawing/painting on screen.

Read more about invokeLater() in
http://java.sun.com/...gUtilities.html
and about swing and threads in
http://java.sun.com/...s/threads1.html

edit: I don't know if this will fix your problem though, because I have not checked your logic (can do this tomorrow if you are still having problems).

This post has been edited by LaFayette: 24 February 2009 - 03:24 PM

Was This Post Helpful? 0
  • +
  • -

#3 onorinbejasus  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 156
  • Joined: 22-February 09

Re: Using Graphics in a thread

Posted 24 February 2009 - 03:52 PM

Thanks for the help, but unfortunately this did not solve the problem.
Was This Post Helpful? 0
  • +
  • -

#4 pbl  Icon User is offline

  • There is nothing you can't do with a JTable
  • member icon

Reputation: 8329
  • View blog
  • Posts: 31,857
  • Joined: 06-March 08

Re: Using Graphics in a thread

Posted 24 February 2009 - 07:04 PM

View Postonorinbejasus, on 24 Feb, 2009 - 02:52 PM, said:

Thanks for the help, but unfortunately this did not solve the problem.

I hope you realize that both threads are using/sharing the same Graphics (that you call canvas)
By doing canvas.setColor(whatever) in any of the 2 threads will affect the SAME Graphics object shared by the 2 threads
Better to have a single class that animate both arms and change, just for the sake of one drawing) the Graphics color

I also doubt that a method like drawLine is thread safe
Better have leftArm and rightARm to extend Arm and have in Arm a synchronized drawLine method

void synchronized drawLine(Graphics g, int x, int y, int x2, int y2) {
   g.drawLine(x, y, x2, y2);
}


then you'll be sure that Graphics is only access by one thread at a time

But this approach is not correct neither...

Your threads should only change the "state" where the arms should be draw... and then call repaint()
this will call paint() with a brand new Graphics object that will react correctly according to the "state" established by the threads

This post has been edited by pbl: 25 February 2009 - 05:36 PM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1