A minha idéia com isso é colocar esse meu pequeno relógio num canto da tela apenas com o mostrador (circular) aparecendo…
Eu sei que esse tipo de coisa já existe, já vem no Vista como Widget, etc… mas eu adoro fuçar nessas coisas!
Por enquanto a parte da transparência está comentada até que eu domine a técnica…
Refatoração à parte, essa é a minha "CRASSE" gigante, porque sendo isso apenas um relógio eu não quis montar uma arquitetura, embora eu tenha criado uma arquitetura que uso para animações e jogos!
O relógio funciona, quem tiver coragem cole o código no Eclipse e execute!
:lol:
[code]import java.awt.AWTException;
import java.awt.AlphaComposite;
import java.awt.BufferCapabilities;
import java.awt.Color;
import java.awt.Composite;
import java.awt.DisplayMode;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.ImageCapabilities;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.BufferCapabilities.FlipContents;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import javax.swing.JFrame;
public final class MiniRelogio extends JFrame implements Runnable, KeyListener, MouseListener {
private static final MiniRelogio instance = new MiniRelogio();
private static final long serialVersionUID = 1L;
public static void main(String... args) {
getInstance().start();
}
private GraphicsDevice graphicsDevice;
private DisplayMode displayMode;
private GraphicsConfiguration graphicsConfiguration;
private int tamanho;
private volatile boolean running;
private Relogio relogio;
private MiniRelogio() {
super("MiniRelogio");
graphicsDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
graphicsConfiguration = graphicsDevice.getDefaultConfiguration();
displayMode = graphicsDevice.getDisplayMode();
tamanho = (int)(0.15 * displayMode.getHeight());
configJanela();
relogio = new Relogio();
}
private void configJanela() {
this.setUndecorated(true);
this.pack();
Insets it = this.getInsets();
this.setSize(tamanho+it.left+it.right, tamanho+it.top+it.bottom);
this.setResizable(false);
this.setIgnoreRepaint(true);
// configTransparencia();
addListeners();
createBufferStrategy();
posicione();
}
// private void configTransparencia() {
// boolean supported = AWTUtilities.isTranslucencySupported(AWTUtilities.Translucency.TRANSLUCENT);
// boolean capable = AWTUtilities.isTranslucencyCapable(graphicsConfiguration);
// if(supported && capable) {
// AWTUtilities.setWindowOpaque(this, false);
// } else {
// AWTUtilities.setWindowOpacity(this, 0);
// }
// }
private void addListeners() {
this.addKeyListener(this);
this.addMouseListener(this);
this.setFocusable(true);
this.addFocusListener(new FocusAdapter(){
public void focusLost(FocusEvent e) {
MiniRelogio.this.requestFocus();
}
});
this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
this.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e) {
MiniRelogio.this.stop();
}
});
}
private void createBufferStrategy() {
try {
this.createBufferStrategy(2, new BufferCapabilities(new ImageCapabilities(true), new ImageCapabilities(true), FlipContents.UNDEFINED));
System.out.println("FlipContents active");
} catch (AWTException e){
// flip is unavailable, create the best you have
this.createBufferStrategy(2);
System.err.println("Warning: FlipContents not available, using best BufferStrategy available");
System.err.println("System error message: "+e.getMessage());
}
}
private void posicione() {
int padding = (int)(0.015 * displayMode.getHeight());
int posX = displayMode.getWidth() - tamanho - padding;
int posY = padding;
this.setLocation(posX, posY);
}
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;
this.setVisible(true);
while(running) {
long time = System.nanoTime();
this.getBufferStrategy().show();
paint();
update();
pause(time);
}
this.dispose();
System.exit(0);
}
private void paint() {
Graphics2D g2 = (Graphics2D)this.getBufferStrategy().getDrawGraphics();
g2.setRenderingHints(DefaultRenderingHints.getInstance());
clearScreen(g2);
relogio.paint(g2);
g2.dispose();
}
private void clearScreen(Graphics2D g2) {
g2.setColor(CompColor.BACKGROUND.getColor());
g2.fillRect(0, 0, tamanho, tamanho);
}
private void update() {
relogio.update();
}
private void pause(long time) {
double fps = 60;
long minPause = 5;
long pauseTime = (long)(1000.0/fps - (double)(System.nanoTime()-time)/1000000.0);
pauseTime = pauseTime > minPause ? pauseTime : minPause;
try {
Thread.sleep(pauseTime);
} catch (InterruptedException e) {}
}
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));
}
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_ESCAPE:
this.stop();
break;
}
}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public static MiniRelogio getInstance() {
return instance;
}
private static class DefaultRenderingHints extends RenderingHints {
private static final DefaultRenderingHints instance = new DefaultRenderingHints();
private DefaultRenderingHints() {
super(null);
this.put(KEY_ALPHA_INTERPOLATION, VALUE_ALPHA_INTERPOLATION_QUALITY);
this.put(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);
this.put(KEY_COLOR_RENDERING, VALUE_COLOR_RENDER_QUALITY);
this.put(KEY_DITHERING, VALUE_DITHER_DISABLE);
this.put(KEY_FRACTIONALMETRICS, VALUE_FRACTIONALMETRICS_ON);
this.put(KEY_INTERPOLATION, VALUE_INTERPOLATION_BILINEAR);
this.put(KEY_RENDERING, VALUE_RENDER_QUALITY);
this.put(KEY_STROKE_CONTROL, VALUE_STROKE_NORMALIZE);
this.put(KEY_TEXT_ANTIALIASING, VALUE_TEXT_ANTIALIAS_ON);
}
private static DefaultRenderingHints getInstance() {
return instance;
}
}
private class Relogio {
int posInterna;
private Integer[] raiosInternos;
private Integer[] raiosExternos;
private int distRaios;
private double aumentaAnguloDe;
private BufferedImage mostrador;
private TimeAngles timeAngles;
private AlphaComposite alphaFundoMostrador;
private AlphaComposite alphaHoras;
private AlphaComposite alphaMinutos;
private AlphaComposite alphaSegundos;
private Font font;
private Relogio() {
posInterna = (int)((double)tamanho / 2.0);
distRaios = (int)((double)tamanho / 40.0);
preparaAlphas();
preparaRaios();
preparaMostrador();
aumentaAnguloDe = 12;
timeAngles = new TimeAngles(new GregorianCalendar());
font = new Font("Courier New", Font.BOLD, (int)(0.05*(double)tamanho));
}
private void preparaAlphas() {
alphaFundoMostrador = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.20F);
alphaHoras = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1F);
alphaMinutos = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7F);
alphaSegundos = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4F);
}
private void preparaRaios() {
List<Integer> raios = new ArrayList<Integer>();
int raioMostrador = (int)((double)tamanho/2.0 - (double)distRaios * 2.0);
int raio = raioMostrador;
do {
raios.add(raio);
raio -= distRaios;
} while(raio > 0);
raiosInternos = raios.toArray(new Integer[]{});
int maiorRaio = (int)Math.pow(2 * (Math.pow((double)tamanho/2.0, 2.0)), 0.5);
raios = new ArrayList<Integer>();
raio = raioMostrador + distRaios;
do {
raios.add(raio);
raio += distRaios;
} while(raio <= maiorRaio);
raiosExternos = raios.toArray(new Integer[]{});
}
private void preparaMostrador() {
mostrador = graphicsConfiguration.createCompatibleImage(tamanho, tamanho, Transparency.TRANSLUCENT);
Graphics2D g2 = mostrador.createGraphics();
g2.setRenderingHints(DefaultRenderingHints.getInstance());
g2.setColor(CompColor.FOREGROUND.getColor());
desenhaCirculos(g2);
desenhaRaios(g2);
desenhaTracos(g2);
desenhaNumeros(g2);
g2.drawRect(0, 0, tamanho-1, tamanho-1);
g2.dispose();
}
private void desenhaCirculos(Graphics2D g2) {
Composite comp = g2.getComposite();
g2.setComposite(alphaFundoMostrador);
int posicao;
int diametro;
for(int raio : raiosInternos) {
posicao = (int)((double)tamanho/2.0-(double)raio);
diametro = raio*2;
g2.drawOval(posicao, posicao, diametro, diametro);
}
for(int raio : raiosExternos) {
posicao = (int)((double)tamanho/2.0-(double)raio);
diametro = raio*2;
g2.drawOval(posicao, posicao, diametro, diametro);
}
g2.setComposite(comp);
posicao = (int)((double)tamanho/2.0-(double)raiosInternos[0]);
diametro = raiosInternos[0]*2;
g2.drawOval(posicao, posicao, diametro, diametro);
}
private void desenhaRaios(Graphics2D g2) {
Composite comp = g2.getComposite();
g2.setComposite(alphaFundoMostrador);
int raio = raiosInternos[0];
for(int angle=0; angle<360; angle+=6) {
int posXExterna = (int)((double)posInterna + getPosX(raio, angle));
int posYExterna = (int)((double)posInterna + getPosY(raio, angle));
g2.drawLine(posInterna, posInterna, posXExterna, posYExterna);
}
int raioMenor = raiosInternos[0];
int raioMaior = raiosExternos[raiosExternos.length-1];
for(int angle=0; angle<360; angle+=3) {
int posXMenor = (int)((double)posInterna + getPosX(raioMenor, angle));
int posYMenor = (int)((double)posInterna + getPosY(raioMenor, angle));
int posXMaior = (int)((double)posInterna + getPosX(raioMaior, angle));
int posYMaior = (int)((double)posInterna + getPosY(raioMaior, angle));
g2.drawLine(posXMenor, posYMenor, posXMaior, posYMaior);
}
g2.setComposite(comp);
}
private void desenhaTracos(Graphics2D g2) {
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)posInterna + getPosX(raiosInternos[raioMenor], angle));
int posYMenor = (int)((double)posInterna + getPosY(raiosInternos[raioMenor], angle));
int posXMaior = (int)((double)posInterna + getPosX(raioMaior, angle));
int posYMaior = (int)((double)posInterna + getPosY(raioMaior, angle));
g2.drawLine(posXMenor, posYMenor, posXMaior, posYMaior);
}
}
private void desenhaNumeros(Graphics2D g2) {
g2.setColor(CompColor.FOREGROUND.getColor());
g2.setFont(font);
FontMetrics fm = g2.getFontMetrics();
double height = fm.getAscent();
int numero = 3;
for(int angulo=0; angulo<360; angulo+=30) {
double width = fm.stringWidth(String.valueOf(numero));
int posX = (int)((double)posInterna + getPosX(raiosInternos[6], angulo) - width / 2.0);
int posY = (int)((double)posInterna + getPosY(raiosInternos[6], angulo) + height / 2.0);
g2.drawString(String.valueOf(numero), posX, posY);
numero = (numero + 1) % 13;
if(numero == 0) numero++;
}
}
public void paint(Graphics2D g2) {
g2.drawImage(mostrador, 0, 0, null);
g2.setColor(CompColor.FOREGROUND.getColor());
desenhaPonteiros(g2);
}
private void desenhaPonteiros(Graphics2D g2) {
int raio = 5;
this.desenhaPonteiro(g2, timeAngles.getSecondAngle(), raio, alphaSegundos);
this.desenhaPonteiro(g2, timeAngles.getMinuteAngle(), raio + 4, alphaMinutos);
this.desenhaPonteiro(g2, timeAngles.getHourAngle(), raio + 8, alphaHoras);
}
private void desenhaPonteiro(Graphics2D g2, double angle, int raio, AlphaComposite alpha) {
Composite comp = g2.getComposite();
g2.setComposite(alpha);
// Desenhando ponteiro
double posXInterna = (double)posInterna + getPosX(raiosInternos[raio+2], angle);
double posYInterna = (double)posInterna + getPosY(raiosInternos[raio+2], angle);
g2.drawLine((int)posInterna, (int)posInterna, (int)posXInterna, (int)posYInterna);
// Desenhando triângulo
double posXExterna = (double)posInterna + getPosX(raiosInternos[raio], angle);
double posYExterna = (double)posInterna + getPosY(raiosInternos[raio], angle);
double posXInterna1 = (double)posInterna + getPosX(raiosInternos[raio+4], (angle-aumentaAnguloDe/2.0));
double posYInterna1 =(double)posInterna + getPosY(raiosInternos[raio+4], (angle-aumentaAnguloDe/2.0));
double posXInterna2 = (double)posInterna + getPosX(raiosInternos[raio+4], (angle+aumentaAnguloDe/2.0));
double posYInterna2 = (double)posInterna + getPosY(raiosInternos[raio+4], (angle+aumentaAnguloDe/2.0));
g2.fillPolygon(new int[]{(int)posXExterna, (int)posXInterna1, (int)posXInterna2, (int)posXExterna}, new int[]{(int)posYExterna, (int)posYInterna1, (int)posYInterna2, (int)posYExterna}, 3);
g2.setComposite(comp);
}
public void update() {
timeAngles = new TimeAngles(new GregorianCalendar());
}
}
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;
}
}
private enum CompColor {
BACKGROUND(
CompColor.mixColor(
new Color[]{
new Color(0x00FF00), // verde
new Color(0x808080), // cinza
new Color(0xFFFFFF)}, // branco
new float[]{
0.30F * 0.25F,
0.30F * 0.75F,
0.70F})),
FOREGROUND(
CompColor.mixColor(
new Color[]{
new Color(0x00FF00), // verde
new Color(0x808080), // cinza
new Color(0x000000)}, // preto
new float[]{
0.60F * 0.25F,
0.60F * 0.75F,
0.40F}));
private Color color;
private CompColor(Color color) {
this.color = color;
}
private static Color mixColor(Color[] colors, float[] weights) {
if(!validArgs(colors, weights)) {
try {
throw new Exception("Argumentos inválidos");
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
float[] comps = new float[4];
for(int i=0; i<colors.length; i++) {
Color color = colors[i];
float weight = weights[i];
comps[0] += (float)color.getRed() * weight;
comps[1] += (float)color.getGreen() * weight;
comps[2] += (float)color.getBlue() * weight;
comps[3] += (float)color.getAlpha() * 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 new Color((int)comps[0], (int)comps[1], (int)comps[2], (int)comps[3]);
}
private static boolean validArgs(Color[] colors, float[] weights) {
if(colors == null || !(colors.length>0) || weights == null || !(weights.length>0) || colors.length != weights.length) {
return false;
}
float sum = 0;
for(float weight : weights) {
if(weight <= 0 || weight >= 1) {
return false;
}
sum += weight;
}
if(sum != 1.0F) {
return false;
}
return true;
}
public Color getColor() {
return color;
}
}
}[/code]