Do tópico AWTUtilities.setWindowOpaque acabei desenvolvendo um aplicativo completo para celular (e outros dispositivos móveis).
É um relógio de display analógico com muitos efeitos, simulação de canal alpha, geração e evolução de cores e outras coisas!
Segue o código fonte completo abaixo.
Como o editor do GUJ às vezes dá uma zoada em alguns caracteres segue também em anexo o arquivo de fonte completo, mais os arquivos compilados pra quem quiser instalar direto no celular!
Funciona em muitos aparelhos, já que usei a configuração mais básica possível (CLDC 1.0 e MIDP 1.0), dimensiona todos os elementos de acordo com o tamanho da tela do aparelho instalado e de lambuja tem um ícone bonitinho empacotado junto, que já aparece após instalar o relógio!
Divirtam-se e me perguntem o que quiserem!
[code]package soft;
import java.util.Calendar;
import java.util.Random;
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 final int FPS = 30;
private Screen screen;
private int baseColor;
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() {
baseColor = (baseColor == 0 ? sortColor() : updateColor(baseColor, 0xF));
backColor = mixColors(
new int[]{
baseColor, // ?
0x808080, // cinza
0xFFFFFF}, // branco
new float[]{
0.30F * 0.25F,
0.30F * 0.75F,
0.70F});
frontColor = mixColors(
new int[]{
baseColor, // ?
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 getColor(new int[]{(int)comps[0], (int)comps[1], (int)comps[2]});
}
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 int sortColor() {
Random rand = new Random();
int[] comps = new int[] {0x00, 0xFF, rand.nextInt(0x100)};
int[] indexes = new int[] {-1, -1, -1};
for(int i=0; i<indexes.length; i++) {
while(indexes[i] == -1) {
int index = rand.nextInt(indexes.length);
boolean exists = false;
for(int j=0; j><i; j++) {
if(indexes[j] == index) {
exists = true;
break;
}
}
if(!exists) {
indexes[i] = index;
}
}
}
return getColor(new int[]{comps[indexes[0]], comps[indexes[1]], comps[indexes[2]]});
}
public int updateColor(int color, double speed) {
int[] comps = getColorComps(color);
int minColor = 0;
int maxColor = 0xFF;
int keyIndex = -1;
for(int i=0; i><comps.length; i++) {
if(comps[i] != minColor && comps[i] != maxColor) {
keyIndex = i;
break;
}
}
if(keyIndex == -1) { // Dois componentes são iguais (mínimo ou o máximo)
for(int i=0; i><comps.length; i++) {
int prox = i + 1;
if(prox >= comps.length) {
prox = 0;
}
if(comps[i] == comps[prox]) { // Sempre o igual anterior é que muda
keyIndex = i;
break;
}
}
}
int leftIndex = keyIndex - 1;
if(leftIndex < 0) {
leftIndex = comps.length - 1;
}
int rightIndex = keyIndex + 1;
if(rightIndex >= comps.length) {
rightIndex = 0;
}
double increment = speed / FPS;
if(increment < 1) increment = 1;
if(comps[keyIndex] >= comps[leftIndex] && comps[keyIndex] <= comps[rightIndex]) {
comps[keyIndex] -= increment;
if(comps[keyIndex] < minColor) {
comps[keyIndex] = minColor;
}
} else {
comps[keyIndex] += increment;
if(comps[keyIndex] > maxColor) {
comps[keyIndex] = maxColor;
}
}
return getColor(comps);
}
private int getColor(int[] comps) {
String finalColor = "";
for(int i=0; i<comps.length; i++) {
finalColor += leftPadding(Integer.toHexString((int)comps[i]), '0', 2);
}
return Integer.parseInt(finalColor, 16);
}
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("Reiniciar", Command.BACK, 1));
this.addCommand(new Command("Sair", Command.EXIT, 2));
}
public void commandAction(Command command, Displayable displayable) {
if(displayable!=this)return;
int type = command.getCommandType();
if(type == Command.EXIT || type == Command.BACK) {
if(type == Command.BACK) {
baseColor = 0;
restart = true;
}
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() {
prepareScreenColors();
relogio.update();
}
private void pause(long time) {
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.75F);
corHoras = getPseudoAlphaColor(frontColor, 1F);
corMinutos = getPseudoAlphaColor(frontColor, 0.75F);
corSegundos = getPseudoAlphaColor(frontColor, 0.5F);
}
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() {
preparaCores();
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;
}
}
}[/code]