CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3
  1. #1
    Join Date
    Oct 2011
    Location
    Tennessee
    Posts
    46

    Question Analog Clock 2x problem

    I am trying to get this clock to tick twice as fast when the "2x Speed" button is clicked. For some reason the clock will jump to another location, when the button is clicked, as if the clock were entirely multiplied by 2, and then the second hand will tick twice as fast. I want to know if anyone can explain why this is so, and how to fix this? I have asked others and they have said that because the button affects the clock as it does is that x2 speed calculation just takes the seconds and doubles them so the second hand is always going to jump if the current seconds value is anything other than a very small number.

    Keang, I believe, said I need to keep a note of the time the x2 was turned on and double the difference between the current time and the start time.

    But even though the button is pushed it will jump first to another location and then start ticking twice as fast. What am I supposed to do?

    The seconds are affected I believe in the paint() function, and the seconds are actually multiplied by 2 in the run()function.

    Thanks for your help.

    Code:
    import java.awt.*;
    import java.awt.event.*;
    import java.text.*;
    import java.util.*;
    import java.applet.*;
    
    public class AnalogClock extends Applet implements ActionListener, Runnable{
    	
    	private static final long serialVersionUID = 1787899701025425670L;
    	Thread t = null;
    	boolean threadSuspended;
    	String timeString = "";
    	
    	
    	Calendar cal = Calendar.getInstance();
    	String regTimeFormat = "hh:mm:ss a";
    	String milTimeFormat = "HH:mm:ss a";
    	SimpleDateFormat formatter = null;
    	
    	int width, height, hrHand, mnHand, secHand, radius = 85, hrLength, mnLength,
    		secLength, cx, cy, x1, y1, x2, y2;
    	
    	private Button buttonMilt;
    	private Button b2xSpeed;
    	private boolean buttonMiltClicked = false;
    	private boolean b2xSpeedClicked = false;
    	
    	public void init()
    	{
    		buttonMilt = new Button("Military Time");
    		add(buttonMilt);
    		buttonMilt.addActionListener(this);
    		
    		b2xSpeed = new Button("2x Speed");
    		add(b2xSpeed);
    		b2xSpeed.addActionListener(this);
    
    		
    		width = getSize().width;	//get width of applet
    		height = getSize().height;	//get height of applet
    		
    		hrLength = 6*radius/10;		//sets hours
    		mnLength = 8*radius/10; 	//sets minutes
    		secLength = 9*radius/10; 	//sets seconds
    		cx = width/2; 				//initialize position cx
    		cy = height/2;				//initialize position cy
    		
    		Calendar cal = Calendar.getInstance();
    		formatter = new SimpleDateFormat(regTimeFormat);
    		timeString = formatter.format(cal.getTime());
    		this.setSize(400, 200);
    		
    		
    		 
    	}
    		
    	public void start() //initialize clock
    	{
    		if(t == null)
    		{
    			t = new Thread(this);
    			t.setPriority(Thread.MIN_PRIORITY);
    			threadSuspended = false;
    			t.start();
    		}
    		else 
    		{
    			if (threadSuspended) 
    			{
    				threadSuspended = false;
    				synchronized(this) 
    				{
    					notify();
    				}
    			}
    		}
    	}
    	
    	public void stop() //stop clock
    	{
    		threadSuspended = true;
    	}
    	
    	public void run() //run clock
    	{
    		try {
    			
    			while(true) 
    			{
    				Calendar cal = Calendar.getInstance();						   //*gets time from the system
    					hrHand = cal.get(Calendar.HOUR_OF_DAY);					   //*gets hour
    				if (hrHand > 12) hrHand -= 12;								   //*if hour exceeds 12 decrease
    					mnHand = cal.get(Calendar.MINUTE);						   //*get minutes
    					//secHand = cal.get(Calendar.SECOND);						   //*get seconds	
    				
    					if (b2xSpeedClicked)
    	        		{
    	        			secHand =  (2*cal.get(Calendar.SECOND));					//*get seconds	
    	        		}
    	        		else
    	        		{
    	        			secHand = cal.get(Calendar.SECOND);						   //*get seconds	
    	        		}
    	        		repaint();
    					
    				if (threadSuspended) 
    				{
    					synchronized(this) 
    					{
    						while (threadSuspended) 
    						{
    							wait();
    						}
    					}
    				}
    				repaint();
    				Thread.sleep(1000);
    			}
    		}
    		catch (InterruptedException e) 
    		{
    		}
    	}
    	
    	
    	public void paint(Graphics g) //paint clock
    	{
    		Graphics2D g2d = (Graphics2D) g; //graphics g2d
    		Graphics2D g2 = (Graphics2D) g; //graphics g2
    		
    		buttonMilt.setLocation(200,25);
    		b2xSpeed.setLocation(200,50);
    		
    		if(hrHand >= 12) //decrease if hour exceeds 12
    			hrHand -= 12;
    		
    		for (int i = 0; i < 60; i++) //tickmarks for loop
    		{
    			g.setColor(Color.black); //color of tickmarks
    			x2 = (int)(cx + radius * Math.sin(i * 2 * Math.PI / 60)); //tickmarks endpoint1
    			y2 = (int)(cy - radius * Math.cos(i * 2 * Math.PI / 60)); //tickmarks endpoint2
    			if (i % 5 != 0)
    			{
    				x1 = (int)(cx + 0.9f * radius * Math.sin(i * 2 * Math.PI / 60)); //length bigticks endpoint1
    				y1 = (int)(cy - 0.9f * radius * Math.cos(i * 2 * Math.PI / 60)); //length bigticks endpoint2
    			}
    			else
    			{
    				x1 = (int)(cx + 0.8f * radius * Math.sin(i * 2 * Math.PI / 60)); //length littleticks endpoint1
    				y1 = (int)(cy - 0.8f * radius * Math.cos(i * 2 * Math.PI / 60)); //length littleticks endpoint2
    			}
    			g.drawLine(x1, y1, x2, y2); //tickmarks
    		}
    		
    		g2d.setFont(getFont()); //sets font of numbers
    		for(int hour = 1; hour <= 12; hour++) //Analog numbers for loop
    		{
    			double angle = (hour-3)*2*Math.PI/12; //angle of numbers
    			int x = (int)(Math.cos(angle)*(width/3))+width/2-5; //endpoint1 of numbers
    			int y = (int)(Math.sin(angle)*(width/3))+width/2+5; //endpoint2 of numbers
    			g.setColor(Color.black); //color of analog numbers
    			g2d.drawString(""+hour, x, y); //Analog numbers
    		}
    		
    		x2 = (int)(cx + hrLength * Math.sin((hrHand + mnHand / 60 + secHand / 3600)
    				* 2 * Math.PI / 12)); //endpoint1 of hour hand
    		y2 = (int)(cy - hrLength * Math.cos((hrHand + mnHand / 60 + secHand / 3600)
    				* 2 * Math.PI / 12)); //endpoint2 of hour hand
    		g.setColor(Color.red); //color of hour hand
    		g2.setStroke(new BasicStroke(2)); //width of hour hand
    		g.drawLine(cx - 1, cy - 1, x2 - 1, y2 - 1); //hour hand
    		g2.setStroke(new BasicStroke(0)); //reset width
    		
    		x2 = (int)(cx + mnLength * Math.sin((mnHand + secHand / 60) * 2 * Math.PI / 60)); //endpoint1 of minute hand
    		y2 = (int)(cy - mnLength * Math.cos((mnHand + secHand / 60) * 2 * Math.PI / 60)); //endpoint2 of minute hand
    		g.setColor(Color.green); //color of minute hand
    		g2.setStroke(new BasicStroke(2)); //width of minute hand
    		g.drawLine(cx - 1, cy - 1, x2 - 1, y2 - 1); //minute hand
    		g2.setStroke(new BasicStroke(0)); // reset width of minute hand
    		
    		x2 = (int)(cx + secLength * Math.sin(secHand * 2 * Math.PI / 60)); //endpoint1 of second hand
    		y2 = (int)(cy - secLength * Math.cos(secHand * 2 * Math.PI / 60)); //endpoint2 of second hand
    		g.setColor(Color.blue); //color of circle
    		g2.setStroke(new BasicStroke(0)); //width of circle
    		g.drawLine(cx - 1, cy - 1, x2 - 1, y2 - 1); //second hand
    		
    		g.setColor(Color.black); //color of circle
    		g2.setStroke(new BasicStroke(2)); //width of circle
    		g.drawOval((width - 2 * radius) / 2, (height - 2 * radius) / 2, 2 * radius,
    				2 * radius); //circle
    		g2.setStroke(new BasicStroke(0)); //reset width
    		
    		g.setColor(Color.black); //color of timer
            Calendar cal = Calendar.getInstance();
            timeString = formatter.format(cal.getTime());
    
    		g.drawString(timeString, 75, height-105); //timer
    		
    	}
    	
    	public void actionPerformed(ActionEvent e) {
    
    		        String formatStr = null;
    		        
    		
    		        if (e.getSource() == buttonMilt) {
    		            buttonMiltClicked = !buttonMiltClicked;
    		            if(buttonMiltClicked)
    		            {
    		                formatStr = milTimeFormat;
    		            }
    		            else 
    		            {
    		                formatStr = regTimeFormat;
    		            }  
    		            formatter = new SimpleDateFormat(formatStr);
    		            repaint();
    		            }
    		        
    	
    
    		        if (e.getSource()==b2xSpeed){
    		        	b2xSpeedClicked = !b2xSpeedClicked;
    		        		
    		        }
    	}
    }

  2. #2
    Join Date
    Oct 2011
    Location
    Tennessee
    Posts
    46

    Question Re: Analog Clock 2x problem

    Another said,
    "(2*cal.get(Calendar.SECOND)) This is because you ARE making it twice as value. If you want it to be twice as fast here is what you need to do.

    Make a variable "quickness" make it an int. Set default value to 1000. Then when they click the button set it to quicknes /= 2; this will cut it in half each time.

    Then, set the Thread.sleep(1000); TO the quickness. WHich is why default was 1000, for one second.

    Thread.sleep(quickness)

    This will speed it up by x2 each time. but remember, x2 twice is actually x4 and so forth.. "

    Resulting code:
    Code:
    import java.awt.*;
    import java.awt.event.*;
    import java.text.*;
    import java.util.*;
    import java.applet.*;
    
    public class AnalogClock extends Applet implements ActionListener, Runnable{
    	
    	private static final long serialVersionUID = 1787899701025425670L;
    	Thread t = null;
    	boolean threadSuspended;
    	String timeString = "";
    	
    	
    	Calendar cal = Calendar.getInstance();
    	String regTimeFormat = "hh:mm:ss a";
    	String milTimeFormat = "HH:mm:ss a";
    	SimpleDateFormat formatter = null;
    	
    	int width, height, hrHand, mnHand, secHand, radius = 85, hrLength, mnLength,
    		secLength, quickness, cx, cy, x1, y1, x2, y2;
    	
    	private Button buttonMilt;
    	private Button b2xSpeed;
    	private boolean buttonMiltClicked = false;
    	private boolean b2xSpeedClicked = false;
    	
    	public void init()
    	{
    		buttonMilt = new Button("Military Time");
    		add(buttonMilt);
    		buttonMilt.addActionListener(this);
    		
    		b2xSpeed = new Button("2x Speed");
    		add(b2xSpeed);
    		b2xSpeed.addActionListener(this);
    		
    		quickness = 1000;
    
    		
    		width = getSize().width;	//get width of applet
    		height = getSize().height;	//get height of applet
    		
    		hrLength = 6*radius/10;		//sets hours
    		mnLength = 8*radius/10; 	//sets minutes
    		secLength = 9*radius/10; 	//sets seconds
    		cx = width/2; 				//initialize position cx
    		cy = height/2;				//initialize position cy
    		
    		Calendar cal = Calendar.getInstance();
    		formatter = new SimpleDateFormat(regTimeFormat);
    		timeString = formatter.format(cal.getTime());
    		this.setSize(400, 200);
    		
    		
    		 
    	}
    		
    	public void start() //initialize clock
    	{
    		if(t == null)
    		{
    			t = new Thread(this);
    			t.setPriority(Thread.MIN_PRIORITY);
    			threadSuspended = false;
    			t.start();
    		}
    		else 
    		{
    			if (threadSuspended) 
    			{
    				threadSuspended = false;
    				synchronized(this) 
    				{
    					notify();
    				}
    			}
    		}
    	}
    	
    	public void stop() //stop clock
    	{
    		threadSuspended = true;
    	}
    	
    	public void run() //run clock
    	{
    		try {
    			
    			while(true) 
    			{
    				Calendar cal = Calendar.getInstance();						   //*gets time from the system
    					hrHand = cal.get(Calendar.HOUR_OF_DAY);					   //*gets hour
    				if (hrHand > 12) hrHand -= 12;								   //*if hour exceeds 12 decrease
    					mnHand = cal.get(Calendar.MINUTE);						   //*get minutes
    					//secHand = cal.get(Calendar.SECOND);						   //*get seconds	
    				
    					if (b2xSpeedClicked)
    	        		{
    						quickness/=2;	
    						//*get seconds	
    	        		}
    	        		else
    	        		{
    	        			secHand = cal.get(Calendar.SECOND);						   //*get seconds	
    	        		}
    	        		repaint();
    					
    				if (threadSuspended) 
    				{
    					synchronized(this) 
    					{
    						while (threadSuspended) 
    						{
    							wait();
    						}
    					}
    				}
    				repaint();
    				Thread.sleep(quickness);
    			}
    		}
    		catch (InterruptedException e) 
    		{
    		}
    	}
    	
    	
    	public void paint(Graphics g) //paint clock
    	{
    		Graphics2D g2d = (Graphics2D) g; //graphics g2d
    		Graphics2D g2 = (Graphics2D) g; //graphics g2
    		
    		buttonMilt.setLocation(200,25);
    		b2xSpeed.setLocation(200,50);
    		
    		if(hrHand >= 12) //decrease if hour exceeds 12
    			hrHand -= 12;
    		
    		for (int i = 0; i < 60; i++) //tickmarks for loop
    		{
    			g.setColor(Color.black); //color of tickmarks
    			x2 = (int)(cx + radius * Math.sin(i * 2 * Math.PI / 60)); //tickmarks endpoint1
    			y2 = (int)(cy - radius * Math.cos(i * 2 * Math.PI / 60)); //tickmarks endpoint2
    			if (i % 5 != 0)
    			{
    				x1 = (int)(cx + 0.9f * radius * Math.sin(i * 2 * Math.PI / 60)); //length bigticks endpoint1
    				y1 = (int)(cy - 0.9f * radius * Math.cos(i * 2 * Math.PI / 60)); //length bigticks endpoint2
    			}
    			else
    			{
    				x1 = (int)(cx + 0.8f * radius * Math.sin(i * 2 * Math.PI / 60)); //length littleticks endpoint1
    				y1 = (int)(cy - 0.8f * radius * Math.cos(i * 2 * Math.PI / 60)); //length littleticks endpoint2
    			}
    			g.drawLine(x1, y1, x2, y2); //tickmarks
    		}
    		
    		g2d.setFont(getFont()); //sets font of numbers
    		for(int hour = 1; hour <= 12; hour++) //Analog numbers for loop
    		{
    			double angle = (hour-3)*2*Math.PI/12; //angle of numbers
    			int x = (int)(Math.cos(angle)*(width/3))+width/2-5; //endpoint1 of numbers
    			int y = (int)(Math.sin(angle)*(width/3))+width/2+5; //endpoint2 of numbers
    			g.setColor(Color.black); //color of analog numbers
    			g2d.drawString(""+hour, x, y); //Analog numbers
    		}
    		
    		x2 = (int)(cx + hrLength * Math.sin((hrHand + mnHand / 60 + secHand / 3600)
    				* 2 * Math.PI / 12)); //endpoint1 of hour hand
    		y2 = (int)(cy - hrLength * Math.cos((hrHand + mnHand / 60 + secHand / 3600)
    				* 2 * Math.PI / 12)); //endpoint2 of hour hand
    		g.setColor(Color.red); //color of hour hand
    		g2.setStroke(new BasicStroke(2)); //width of hour hand
    		g.drawLine(cx - 1, cy - 1, x2 - 1, y2 - 1); //hour hand
    		g2.setStroke(new BasicStroke(0)); //reset width
    		
    		x2 = (int)(cx + mnLength * Math.sin((mnHand + secHand / 60) * 2 * Math.PI / 60)); //endpoint1 of minute hand
    		y2 = (int)(cy - mnLength * Math.cos((mnHand + secHand / 60) * 2 * Math.PI / 60)); //endpoint2 of minute hand
    		g.setColor(Color.green); //color of minute hand
    		g2.setStroke(new BasicStroke(2)); //width of minute hand
    		g.drawLine(cx - 1, cy - 1, x2 - 1, y2 - 1); //minute hand
    		g2.setStroke(new BasicStroke(0)); // reset width of minute hand
    		
    		x2 = (int)(cx + secLength * Math.sin(secHand * 2 * Math.PI / 60)); //endpoint1 of second hand
    		y2 = (int)(cy - secLength * Math.cos(secHand * 2 * Math.PI / 60)); //endpoint2 of second hand
    		g.setColor(Color.blue); //color of circle
    		g2.setStroke(new BasicStroke(0)); //width of circle
    		g.drawLine(cx - 1, cy - 1, x2 - 1, y2 - 1); //second hand
    		
    		g.setColor(Color.black); //color of circle
    		g2.setStroke(new BasicStroke(2)); //width of circle
    		g.drawOval((width - 2 * radius) / 2, (height - 2 * radius) / 2, 2 * radius,
    				2 * radius); //circle
    		g2.setStroke(new BasicStroke(0)); //reset width
    		
    		g.setColor(Color.black); //color of timer
            Calendar cal = Calendar.getInstance();
            timeString = formatter.format(cal.getTime());
    
    		g.drawString(timeString, 75, height-105); //timer
    		
    	}
    	
    	public void actionPerformed(ActionEvent e) {
    
    		        String formatStr = null;
    		        
    		
    		        if (e.getSource() == buttonMilt) {
    		            buttonMiltClicked = !buttonMiltClicked;
    		            if(buttonMiltClicked)
    		            {
    		                formatStr = milTimeFormat;
    		            }
    		            else 
    		            {
    		                formatStr = regTimeFormat;
    		            }  
    		            formatter = new SimpleDateFormat(formatStr);
    		            repaint();
    		            }
    		        
    	
    
    		        if (e.getSource()==b2xSpeed){
    		        	b2xSpeedClicked = !b2xSpeedClicked;
    		        		
    		        }
    	}
    }
    The problem is that when the "2x Speed is clicked the clock blinks and then gets quicker in blinking as the second hand stays there frozen. Like the clock is having a seizure or something?

    What is going on?

  3. #3
    Join Date
    May 2006
    Location
    UK
    Posts
    4,473

    Re: Analog Clock 2x problem

    Please don't start a new thread when dealing with the same problem or all the history is lost to new readers (and me because I can't remember in detail everything I've previously advised to every thread I post on).

    Keang, I believe, said I need to keep a note of the time the x2 was turned on and double the difference between the current time and the start time.
    Yes, that's what I said to do.
    But even though the button is pushed it will jump first to another location and then start ticking twice as fast. What am I supposed to do?
    You do what I said to do.

    What's the problem here - I told you the solution and you haven't coded it yet as far as you have shown here or in the other thread and you are complaining you can't get it to work. Show the code with my solution and tell me why it isn't working and I will help you sort it out.

    Another said,
    "(2*cal.get(Calendar.SECOND)) This is because you ARE making it twice as value. If you want it to be twice as fast here is what you need to do.
    This won't work unless you abandon using the system clock and rely on incrementing the seconds each time through the loop. The danger with doing this is drift ie the time will drift away from the system clock over time as each iteration of the loop won't be exactly a second (or 0.5 seconds when in x2 mode).
    If you want to use this approach then use a java.util.Timer and call scheduleAtFixedRate(..) to prevent the drift problem.
    Posting code? Use code tags like this: [code]...Your code here...[/code]
    Click here for examples of Java Code

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured