I am doing a project in which i have to create a set of 6 clocks showing different times for different places using java GUI. I have successfully created the code for showing one clock using threading. But how to create 6 different threads to handle the 6 clocks?
This is the following class which creates a single clock:
public class analogClockGUI extends JPanel implements Runnable{
int secx,secy,lsecx,lsecy;
int minx,miny,lminx,lminy;
int hrx,hry,lhrx,lhry;
int secRadius,minRadius,hrRadius,center;
int pointx1,pointy1,pointx2,pointy2;
double dhs,dhm,dhh;
Random rndm;
Thread t;
Font clockFont;
Date incre;
int s,h,m;
boolean off=false,drawFirst=true;
Dimension dimension;
Color wallColor,backColor=Color.black;
int previousMin,previousSec;
int change;
public analogClockGUI()
{
addMouseListener(new MouseAdapter()
{
public void mouseEntered(MouseEvent me)
{
dimension=getSize();
if(change!=dimension.height)
{
center=dimension.height/2;
setSize(new Dimension(dimension.height,dimension.height));
}
/*else
{
center=dimension.width/2;
setSize(new Dimension(dimension.width,dimension.width));
}*/
drawFirst=true;
change=dimension.height;
secRadius=(int)(0.7*center);
minRadius=(int)(0.75*center);
hrRadius=(int)(0.5*center);
}
});
init();
}
public void init()
{
rndm=new Random();
t=new Thread(this);
dimension=getSize();
center=dimension.height/2;
secRadius=(int)(0.7*center);
minRadius=(int)(0.75*center);
hrRadius=(int)(0.5*center);
wallColor=new Color(rndm.nextInt(255),rndm.nextInt(255),rndm.nextInt(255));
t.start();
}
public void run() throws NullPointerException
{
while(true)
{
s=new Date().getSeconds();//+incre.getSeconds();
if(s!=previousSec)
{
dhs=Math.toRadians(s*6-90);
secx=(int)(secRadius*Math.cos(dhs))+center;
secy=(int)(secRadius*Math.sin(dhs))+center;
pointx1=(int)((secRadius+center*0.15)*Math.cos(dhs))+center;
pointy1=(int)((secRadius+center*0.15)*Math.sin(dhs))+center;
m=new Date().getMinutes();
dhm=Math.toRadians(m*6-90);
minx=(int)(minRadius*Math.cos(dhm))+center;
miny=(int)(minRadius*Math.sin(dhm))+center;
pointx2=(int)((secRadius+center*0.15)*Math.cos(dhm))+center;
pointy2=(int)((secRadius+center*0.15)*Math.sin(dhm))+center;
h =new Date().getHours();
dhh=Math.toRadians(h*30-90+((m-1)/2));
hrx=(int)(hrRadius*Math.cos(dhh))+center;
hry=(int)(hrRadius*Math.sin(dhh))+center;
repaint();
previousSec=s;
}
try
{
Thread.sleep(100);
if(off)
break;
}catch(InterruptedException e){}
}
}
public void upgate(Graphics g) throws NullPointerException
{
if(drawFirst==true)
{
clockFont=new Font("Serif",Font.PLAIN,(int)(0.2*center));
drawFirst=false;
}
if(m!=previousMin){
if(s==0)
{
wallColor=new Color(rndm.nextInt(255),rndm.nextInt(255),rndm.nextInt(255));
g.setColor(wallColor);
g.fillOval(0,0,2*center,2*center);
g.setColor(backColor);
g.fillOval((int)(0.1*center),(int)(0.1*center),(int)(center*1.8),(int)(center*1.8));
clear(g);
previousMin=m;
}}
drawPoints(g);
g.setColor(Color.white);
g.setFont(clockFont);
g.drawString("12",(int)(0.9*center),(int)(0.25*center));
g.drawString("6",(int)(0.95*center),(int)(1.885*center));
g.drawString("9",(int)(0.11*center),(int)(1.06*center));
g.drawString("3",(int)(1.805*center),(int)(1.07*center));
g.drawString("1",(int)(1.369*center),(int)(0.36*center));
g.drawString("2",(int)(1.674*center),(int)(0.645*center));
g.drawString("4",(int)(1.665*center),(int)(1.485*center));
g.drawString("5",(int)(1.372*center),(int)(1.778*center));
g.drawString("7",(int)(0.545*center),(int)(1.777*center));
g.drawString("8",(int)(0.227*center),(int)(1.485*center));
g.drawString("10",(int)(0.212*center),(int)(0.675*center));
g.drawString("11",(int)(0.522*center),(int)(0.365*center));
if(lsecx!=0)
{
g.setColor(backColor);
g.drawLine(center,center,lsecx,lsecy);
}
g.setColor(Color.green);
g.drawLine(center,center,hrx,hry);
g.drawLine(center+1,center,hrx,hry);
g.drawLine(center-1,center,hrx,hry);
g.drawLine(center,center+1,hrx,hry);
g.drawLine(center,center-1,hrx,hry);
g.drawLine(center+2,center,hrx,hry);
g.drawLine(center-2,center,hrx,hry);
g.drawLine(center,center+2,hrx,hry);
g.drawLine(center,center-2,hrx,hry);
//show the minute hand with bigger size
g.setColor(Color.blue);
g.drawLine(center,center,minx,miny);
g.drawLine(center+1,center,minx,miny);
g.drawLine(center-1,center,minx,miny);
g.drawLine(center,center+1,minx,miny);
g.drawLine(center,center-1,minx,miny);
g.setColor(Color.red);
g.drawLine(center,center,secx,secy);
g.fillOval(center-3,center-3,6,6); //center point
if(m%5!=0)
{
g.setColor(Color.cyan);
g.fillOval(pointx2-2,pointy2-2,4,4);
}
if(s%5!=0)
{
g.setColor(Color.red);
g.fillOval(pointx1-2,pointy1-2,4,4);
}
lminx=minx;
lminy=miny;
lhrx=hrx;
lhry=hry;
lsecx=secx;
lsecy=secy;
}
public void paint(Graphics g) throws NullPointerException
{
g.setColor(wallColor);
g.fillOval(0,0,2*center,2*center);
g.setColor(backColor);
g.fillOval((int)(0.1*center),(int)(0.1*center),(int)(center*1.8),(int)(center*1.8));
upgate(g);
}
public void clear(Graphics g) throws NullPointerException
{
if(lsecx!=0)
{
g.setColor(backColor);
g.drawLine(center,center,lhrx,lhry);
g.drawLine(center+1,center,lhrx,lhry);
g.drawLine(center-1,center,lhrx,lhry);
g.drawLine(center,center+1,lhrx,lhry);
g.drawLine(center,center-1,lhrx,lhry);
g.drawLine(center+2,center,lhrx,lhry);
g.drawLine(center-2,center,lhrx,lhry);
g.drawLine(center,center+2,lhrx,lhry);
g.drawLine(center,center-2,lhrx,lhry);
g.drawLine(center,center,lminx,lminy);
g.drawLine(center+1,center,lminx,lminy);
g.drawLine(center-1,center,lminx,lminy);
g.drawLine(center,center+1,lminx,lminy);
g.drawLine(center,center-1,lminx,lminy);
}
}
public void drawPoints(Graphics g) throws NullPointerException
{
int x1,y1;
double p;
for(int i=1;i<=60;i++)
{
if(i%5!=0)
{
p=i*0.10472;
x1=(int)((secRadius+center*0.15)*Math.cos(p))+center;
y1=(int)((secRadius+center*0.15)*Math.sin(p))+center;
g.setColor(Color.gray);
g.fillOval(x1-2,y1-2,4,4);
}
}
}
public void stop() throws NullPointerException /*close the thread when applet stopped*/
{
off=true;
t=null;
}
}
Your biggest problem is in your
Thread#runcode…Every instance of you clock is using the sameDatevalue.The other problem you have is that you shouldn’t be modifying the values that the UI relies on within the content of the thread…
The problem is, the UI could be updated, before all the values are updated, causing strange and unpredictable paint artifices.
And do you really need a 100 milisecond update?? I would be better to scale out the sleep to 500 milliseconds, putting either slight early or slight late behind the second change.
You painting also freaks me out. Be VERY careful,
JPanelalready has a method calledupdate(Graphics)inherited fromContainer, you could end up with a naming conflict that would crash your program (asupdateis used by the repaint engine`)Very rarely should you need to override
paintdirectly, it is preferred that you usepaintComponent. This ensures that the component is updated and prepared properly on each paint cycle. As part of the process,paintComponentwill also clear the graphics context, so there should be no need for theclearmethod (so long as you honoring the paint chain and callingsuper.paintComponentIdeas and solutions
What I would do, is set up a “ticker” class, whose sole responsibility is to notify registered classes that a “tick” has occurred. In this class, I would use a
javax.swing.Timer. This would force “tick” events to be called from within the context of the Event Dispatching Thread, ensuring that changes to the variables that the paint methods rely on are updated within the context of the same thread. I might consider using a delay of something like 250 milliseconds, allowing for some extra fudge in the notification cycle.Regardless of whether use or a
ThreadorTimer, you’re going to end up with a bottle neck as you update the “ticks”.I would also consider painting the face of the clock to a
BufferedImage, as it’s not likely to change unless the size of the component changes. This will make the paints quicker.