AWTUtilities.setWindowOpaque

6 respostas
Fox_McCloud

Estou testando os seguintes métodos dentro de um JFrame:

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 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()); } }
O detalhe é que quando eu pego o Graphics do BufferStrategy e desenho nele, o desenho fica invisível junto com a janela!

Como eu posso deixar uma janela invisível e desenhar conteúdo nela usando o BufferStrategy, que não está presente no JPanel e outros componentes?

6 Respostas

Fox_McCloud

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:

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;
		}
		
	}
	
}
Fox_McCloud

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).

Que eu acabei de adaptar!

:wink:

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;
		}
		
	}
	
}
Fox_McCloud

Hum… o editor do GUJ trocou algumas coisas… como um < por ><…

Detesto isso!

Bom, segue o fonte (da versão J2ME) em anexo!

Marky.Vasconcelos

Voce pode extender Canvas que funciona como um JPanel e pode ser adicionado no JFrame

Fox_McCloud

Já tentei… fica invisível junto!

Mas quando eu adiciono um JButton ele fica visível…

Agora ou eu faço engenharia reversa nos fontes pra descobrir como o botão fica viível…

:roll:

Ou alguém me conta o segredo!

:stuck_out_tongue:

Fox_McCloud

Pronto, aqui está a versão mais atual do relógio em J2ME e com vários efeitos interessantes, creio ser uma boa fonte de estudos!

Já que isso sai do assunto do tópico, está em um novo tópico:

Relógio analógico completo em J2ME

Divirtam-se!

:wink:

Criado 4 de maio de 2009
Ultima resposta 5 de mai. de 2009
Respostas 6
Participantes 2