Se recomienda el uso de Swing timers para la realización de tareas relacionadas con la interfaz de usuario (GUI-task) ya que todos los timers comparten un mismo hilo y todas las tareas se ejecutan automáticamente en el hilo de despacho de eventos (event-dispatch thread).
Su uso es muy fácil, cuando creamos el timer, especificamos un action listener que se notificará cuando el temporizador acaba. Es válido tanto para tareas repetitivas como para realizar una sola tarea transcurrido un cierto retraso, para este último fin podremos invocar setRepeats(false) en el timer.
Para inciarlo se llama a su método start(), para suspenderlo llamamos a stop().
//Timer Timer timer = new Timer(TIMER_UPDATE, new ActionListener() { public void actionPerformed(ActionEvent e) { // Tareas repetitivas... } }); timer.start();
Como ejemplo de uso de un Swing timer, les presento la implementación de un reloj analógico hecho con Swing.
Este sería el resultado y aquí a continuación os dejo el código.
En primer lugar nuestra clase reloj que definirá y arrancará el Timer.
package reloj; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Calendar; import javax.swing.JPanel; import javax.swing.Timer; public class Reloj extends JPanel { /** Tiempo de actualizacion. */ private static final int TIMER_UPDATE = 1000; /** Calendar. */ private Calendar calendar = null; /** * Constructor. */ public Reloj() { setUI(new RelojUI()); //Inicializamos el calendario calendar = Calendar.getInstance(); //Establecemos el tamaño a nuestro panel setPreferredSize(new Dimension(295, 270)); //Timer para actualizar el calendario Timer timer = new Timer(TIMER_UPDATE, new ActionListener() { public void actionPerformed(ActionEvent e) { //Añadimos 1 segundo al calendario calendar.add(Calendar.SECOND, 1); // repintamos repaint(); } }); timer.start(); } /** * Recupera la instancia de Calendar * @return calendar */ public Calendar getCalendar() { return this.calendar; } }Con cada iteración del Timer llamamos al método repaint() de nuestro reloj, repintando así las manecillas de acuerdo a la hora actual que nos devolvera la instancia de Calendar que hemos definido y actualizaremos también con cada iteración.
A continuación el UI del reloj, que se encargará de redibujarlo cada segundo según establecimos en el retardo del Timer.
package reloj; import java.awt.BasicStroke; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.geom.Ellipse2D; import java.net.URL; import java.util.Calendar; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.PanelUI; public class RelojUI extends PanelUI { private ImageIcon backgroundImage = null; private BasicStroke handsStroke; public static ComponentUI createUI(JComponent c) { return new RelojUI(); } @Override public void installUI(JComponent c) { super.installUI(c); //Hacemos el panel transparente c.setOpaque(false); backgroundImage = createImage("imagenes/reloj.jpg"); // pincel que utilizaremos para las manecillas de los minutos y horas handsStroke = new BasicStroke(2f); } @Override public void paint(Graphics g, JComponent c) { Graphics2D g2d = (Graphics2D) g; // imagen de fondo if (backgroundImage != null) { g2d.drawImage(backgroundImage.getImage(), 0, 0, null); } Reloj reloj = (Reloj) c; int hour = reloj.getCalendar().get(Calendar.HOUR); int minute = reloj.getCalendar().get(Calendar.MINUTE); int second = reloj.getCalendar().get(Calendar.SECOND); // acotamos la parte donde dibujaremos las manecillas del reloj Shape oval = new Ellipse2D.Double(0, 0, 167, 164); int centerX = (int) (oval.getBounds().getWidth() / 2); int centerY = (int) (oval.getBounds().getHeight() / 2); // puntos donde acaban las manecillas del reloj int xh, yh, xm, ym, xs, ys; // calculamos la posicion de las manecillas del reloj xs = (int) (Math.cos(second * Math.PI / 30 - Math.PI / 2) * 75 + centerX); ys = (int) (Math.sin(second * Math.PI / 30 - Math.PI / 2) * 75 + centerY); xm = (int) (Math.cos(minute * Math.PI / 30 - Math.PI / 2) * 60 + centerX); ym = (int) (Math.sin(minute * Math.PI / 30 - Math.PI / 2) * 60 + centerY); xh = (int) (Math.cos((hour * 30 + minute / 2) * Math.PI / 180 - Math.PI / 2) * 45 + centerX); yh = (int) (Math.sin((hour * 30 + minute / 2) * Math.PI / 180 - Math.PI / 2) * 45 + centerY); //offset, movemos el origen de las coordenadas usadas para dibujar //al vertice superior izquierdo del rectángulo que contiene la esfera del reloj. g.translate(48, 78); //dibujamos los numeros y las manecillas g.drawString("9", 10, centerY+5); g.drawString("3", (int) (oval.getBounds().getWidth() - 10), centerY+5); g.drawString("12", centerX-6, 20); g.drawString("6", centerX-3, (int) (oval.getBounds().getHeight() - 10)); // segundos g.drawLine(centerX, centerY, xs, ys); // minutos g2d.setStroke(handsStroke); g.drawLine(centerX, centerY, xm, ym); //horas g.drawLine(centerX, centerY, xh, yh); // - offset g.translate(-47, -78); } /** * Para recuperar una imagen de un archivo... * @param path Ruta de la imagen relativa al proyecto * @return una imagen */ public ImageIcon createImage(String path) { URL imgURL = getClass().getResource(path); if (imgURL != null) { return new ImageIcon(imgURL); } else { System.err.println("Couldn't find file: " + path); return null; } } }Y por último la clase main que lanzará la aplicación.
package reloj; import javax.swing.JFrame; public class Main { private static void createAndShowGUI() { JFrame frame = new JFrame("Reloj con Swing"); Reloj reloj = new Reloj(); frame.getContentPane().add(reloj); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(302, 302); frame.setVisible(true); } public static void main(String[] args) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } }
Un saludo y hasta la próxima!