Bom, segue também o código completo da versão desse relógio de display analógico em J2ME (para dispositivos móveis / celulares).
import java.util.Calendar;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
public final class MiniRelogio extends MIDlet {
private Screen screen;
private int frontColor;
private int backColor;
protected void destroyApp(boolean restart) throws MIDletStateChangeException {
if(!restart) {
this.notifyDestroyed();
} else {
this.startApp();
}
}
protected void pauseApp() {
this.notifyPaused();
}
protected void startApp() throws MIDletStateChangeException {
prepareScreenColors();
screen = new Screen();
Display.getDisplay(this).setCurrent(screen);
screen.start();
}
private void finalize() {
Display.getDisplay(this).setCurrent(null);
try {
destroyApp(screen.isRestart());
} catch (MIDletStateChangeException e) {
System.exit(0);
}
}
private void prepareScreenColors() {
backColor = mixColors(
new int[]{
0x00FF00, // verde
0x808080, // cinza
0xFFFFFF}, // branco
new float[]{
0.30F * 0.25F,
0.30F * 0.75F,
0.70F});
frontColor = mixColors(
new int[]{
0x00FF00, // verde
0x808080, // cinza
0x000000}, // preto
new float[]{
0.60F * 0.25F,
0.60F * 0.75F,
0.40F});
}
private double getPosX(double raio, double angle) {
// raio * cos angulo
return raio * Math.cos(Math.toRadians(angle));
}
private double getPosY(double raio, double angle) {
// raio * sin angulo
return raio * Math.sin(Math.toRadians(angle));
}
private int getPseudoAlphaColor(int color, float alpha) {
float alphaBack = 1F - alpha;
return mixColors(
new int[]{backColor, color},
new float[]{alphaBack, alpha});
}
private int mixColors(int[] colors, float[] weights) {
float[] comps = new float[3];
for(int i=0; i<colors.length; i++) {
int[] color = getColorComps(colors[i]);
float weight = weights[i];
comps[0] += (float)color[0] * weight;
comps[1] += (float)color[1] * weight;
comps[2] += (float)color[2] * weight;
}
for(int i=0; i><comps.length; i++) {
if(comps[i] >< 0) {
comps[i] = 0;
} else if(comps[i] > 0xFF) {
comps[i] = 0xFF;
}
}
return Integer.parseInt(
leftPadding(Integer.toHexString((int)comps[0]), '0', 2) +
leftPadding(Integer.toHexString((int)comps[1]), '0', 2) +
leftPadding(Integer.toHexString((int)comps[2]), '0', 2),
16);
}
int[] getColorComps(int color) {
String sColor = leftPadding(Integer.toHexString(color), '0', 6);
return new int[] {
Integer.parseInt(sColor.substring(0, 2), 16),
Integer.parseInt(sColor.substring(2, 4), 16),
Integer.parseInt(sColor.substring(4, 6), 16),
};
}
private String leftPadding(String text, char c, int size) {
while(text.length() < size) {
text = c + text;
}
return text;
}
private class Screen extends GameCanvas implements Runnable, CommandListener {
private volatile boolean running;
private volatile boolean restart;
private Relogio relogio;
protected Screen() {
super(true);
this.setCommandListener(this);
addCommands();
relogio = new Relogio(new int[]{getWidth(), getHeight()});
}
private void addCommands() {
this.addCommand(new Command("Sair", Command.EXIT, 1));
}
public void commandAction(Command command, Displayable displayable) {
if(displayable!=this)return;
if(command.getCommandType() == Command.EXIT) {
stop();
}
}
private void start() {
Thread t = new Thread(this);
t.setPriority(Thread.MAX_PRIORITY);
t.start();
}
private void stop() {
running = false;
}
public void run() {
running = true;
while(running) {
long time = System.currentTimeMillis();
this.flushGraphics();
paint();
update();
pause(time);
}
finalize();
}
private void paint() {
Graphics g = this.getGraphics();
clearScreen(g);
relogio.paint(g);
}
private void clearScreen(Graphics g) {
g.setColor(backColor);
g.fillRect(0, 0, getWidth(), getHeight());
}
private void update() {
relogio.update();
}
private void pause(long time) {
double fps = 30;
long minPause = 5;
long pauseTime = (long)(1000.0/fps - (double)(System.currentTimeMillis()-time));
pauseTime = pauseTime > minPause ? pauseTime : minPause;
try {
Thread.sleep(pauseTime);
} catch (InterruptedException e) {}
}
public boolean isRestart() {
return restart;
}
}
private class Relogio {
private final int LARGURA = 0;
private final int ALTURA = 1;
private final int ANCHOR = Graphics.TOP | Graphics.LEFT;
private int[] tamanho;
private int menorRaio;
private int posX;
private int posY;
private int[] raiosInternos;
private int[] raiosExternos;
private int distRaios;
private double aumentaAnguloDe;
private TimeAngles timeAngles;
private int corFundoMostrador;
private int corNumeros;
private int corHoras;
private int corMinutos;
private int corSegundos;
private Font font;
private Relogio(int[] tamanho) {
this.tamanho = tamanho;
menorRaio = (int)((double)Math.min(tamanho[LARGURA], tamanho[ALTURA])/2.0);
posX = (int)((double)tamanho[LARGURA] / 2.0);
posY = (int)((double)tamanho[ALTURA] / 2.0);
distRaios = (int)((double)menorRaio / 20.0);
preparaCores();
preparaRaios();
aumentaAnguloDe = 12;
timeAngles = new TimeAngles(Calendar.getInstance());
font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
}
private void preparaCores() {
corFundoMostrador = getPseudoAlphaColor(frontColor, 0.20F);
corNumeros = getPseudoAlphaColor(frontColor, 0.5F);
corHoras = getPseudoAlphaColor(frontColor, 1F);
corMinutos = getPseudoAlphaColor(frontColor, 0.7F);
corSegundos = getPseudoAlphaColor(frontColor, 0.4F);
}
private void preparaRaios() {
int raioMostrador = (int)((double)menorRaio - (double)distRaios * 2.0);
int tamanhoVetor = 0;
for(int raio=raioMostrador; raio>0; raio-=distRaios) {
tamanhoVetor++;
}
raiosInternos = new int[tamanhoVetor];
for(int raio=raioMostrador, i=0; raio>0; raio-=distRaios, i++) {
raiosInternos[i] = raio;
}
int maiorRaio = (int)Math.sqrt(((double)(tamanho[LARGURA] * tamanho[LARGURA]) + (double)(tamanho[ALTURA] * tamanho[ALTURA]))/4.0);
tamanhoVetor = 0;
for(int raio=(raioMostrador+distRaios); raio<=maiorRaio; raio+=distRaios) {
tamanhoVetor++;
}
raiosExternos = new int[tamanhoVetor];
for(int raio=(raioMostrador+distRaios), i=0; raio<=maiorRaio; raio+=distRaios, i++) {
raiosExternos[i] = raio;
}
}
public void paint(Graphics g) {
g.setColor(frontColor);
desenhaMostrador(g);
desenhaPonteiros(g);
}
private void desenhaMostrador(Graphics g) {
desenhaCirculos(g);
desenhaRaios(g);
desenhaTracos(g);
desenhaNumeros(g);
g.drawRect(0, 0, tamanho[LARGURA]-1, tamanho[ALTURA]-1);
}
private void desenhaCirculos(Graphics g) {
int cor = g.getColor();
g.setColor(corFundoMostrador);
int diametro;
for(int i=0; i<raiosInternos.length; i++) {
int raio = raiosInternos[i];
int posX = this.posX-raio;
int posY = this.posY-raio;
diametro = raio*2;
g.drawArc(posX, posY, diametro, diametro, 0, 360);
}
for(int i=0; i><raiosExternos.length; i++) {
int raio = raiosExternos[i];
int posX = this.posX-raio;
int posY = this.posY-raio;
diametro = raio*2;
g.drawArc(posX, posY, diametro, diametro, 0, 360);
}
g.setColor(cor);
int raio = raiosInternos[0];
int posX = this.posX-raio;
int posY = this.posY-raio;
diametro = raio*2;
diametro = raio*2;
g.drawArc(posX, posY, diametro, diametro, 0, 360);
}
private void desenhaRaios(Graphics g) {
int cor = g.getColor();
g.setColor(corFundoMostrador);
int raioMenor = raiosInternos[raiosInternos.length - 3];
int raioMaior = raiosInternos[0];
for(int angle=0; angle><360; angle+=6) {
int posXMenor = (int)((double)posX + getPosX(raioMenor, angle));
int posYMenor = (int)((double)posY + getPosY(raioMenor, angle));
int posXMaior = (int)((double)posX + getPosX(raioMaior, angle));
int posYMaior = (int)((double)posY + getPosY(raioMaior, angle));
g.drawLine(posXMenor, posYMenor, posXMaior, posYMaior);
}
raioMenor = raiosInternos[0];
raioMaior = raiosExternos[raiosExternos.length-1];
for(int angle=0; angle<360; angle+=3) {
int posXMenor = (int)((double)posX + getPosX(raioMenor, angle));
int posYMenor = (int)((double)posY + getPosY(raioMenor, angle));
int posXMaior = (int)((double)posX + getPosX(raioMaior, angle));
int posYMaior = (int)((double)posY + getPosY(raioMaior, angle));
g.drawLine(posXMenor, posYMenor, posXMaior, posYMaior);
}
g.setColor(cor);
}
private void desenhaTracos(Graphics g) {
int raioMaior = raiosExternos[0];
int raioMenor;
for(int angle=0; angle<360; angle+=6) {
raioMenor = 1;
if(angle % 90 == 0) {
raioMenor = 3;
} else if (angle % 30 == 0) {
raioMenor = 2;
}
int posXMenor = (int)((double)posX + getPosX(raiosInternos[raioMenor], angle));
int posYMenor = (int)((double)posY + getPosY(raiosInternos[raioMenor], angle));
int posXMaior = (int)((double)posX + getPosX(raioMaior, angle));
int posYMaior = (int)((double)posY + getPosY(raioMaior, angle));
g.drawLine(posXMenor, posYMenor, posXMaior, posYMaior);
}
}
private void desenhaNumeros(Graphics g) {
int cor = g.getColor();
g.setColor(corNumeros);
g.setFont(font);
double height = font.getHeight();
int numero = 3;
for(int angulo=0; angulo<360; angulo+=30) {
double width = font.stringWidth(String.valueOf(numero));
int posX = (int)((double)this.posX + getPosX(raiosInternos[6], angulo) - width / 2.0);
int posY = (int)((double)this.posY + getPosY(raiosInternos[6], angulo) - height / 2.0);
g.drawString(String.valueOf(numero), posX, posY, ANCHOR);
numero = (numero + 1) % 13;
if(numero == 0) numero++;
}
g.setColor(cor);
}
private void desenhaPonteiros(Graphics g) {
int raio = 4;
this.desenhaPonteiro(g, timeAngles.getSecondAngle(), raio, corSegundos);
this.desenhaPonteiro(g, timeAngles.getMinuteAngle(), raio + 3, corMinutos);
this.desenhaPonteiro(g, timeAngles.getHourAngle(), raio + 6, corHoras);
}
private void desenhaPonteiro(Graphics g, double angle, int raio, int novaCor) {
int cor = g.getColor();
g.setColor(novaCor);
// Desenhando ponteiro
double posXInterna = (double)posX + getPosX(raiosInternos[raio+2], angle);
double posYInterna = (double)posY + getPosY(raiosInternos[raio+2], angle);
g.drawLine(posX, posY, (int)posXInterna, (int)posYInterna);
// Desenhando triângulo
double posXExterna = (double)posX + getPosX(raiosInternos[raio], angle);
double posYExterna = (double)posY + getPosY(raiosInternos[raio], angle);
double posXInterna1 = (double)posX + getPosX(raiosInternos[raio+4], (angle-aumentaAnguloDe/2.0));
double posYInterna1 =(double)posY + getPosY(raiosInternos[raio+4], (angle-aumentaAnguloDe/2.0));
double posXInterna2 = (double)posX + getPosX(raiosInternos[raio+4], (angle+aumentaAnguloDe/2.0));
double posYInterna2 = (double)posY + getPosY(raiosInternos[raio+4], (angle+aumentaAnguloDe/2.0));
g.drawLine((int)posXExterna, (int)posYExterna, (int)posXInterna1, (int)posYInterna1);
g.drawLine((int)posXExterna, (int)posYExterna, (int)posXInterna2, (int)posYInterna2);
g.setColor(cor);
}
public void update() {
timeAngles = new TimeAngles(Calendar.getInstance());
}
}
private class TimeAngles {
private double hour;
private double minute;
private double second;
private double millisecond;
public TimeAngles(Calendar calendar) {
hour = calendar.get(Calendar.HOUR_OF_DAY);
minute = calendar.get(Calendar.MINUTE);
second = calendar.get(Calendar.SECOND);
millisecond = calendar.get(Calendar.MILLISECOND);
}
public double getMillisecondAngle() {
double time = millisecond/1000;
return getAngle(time);
}
public double getSecondAngle() {
double time = (second + millisecond/1000)/60;
return getAngle(time);
}
public double getMinuteAngle() {
double time = (minute + second/60)/60;
return getAngle(time);
}
public double getHourAngle() {
double time = (hour + minute/60 + second/3600 + millisecond/3600000)/12;
return getAngle(time);
}
private double getAngle(double time) {
return (time * 360) - 90;
}
}
}