2011-08-31 36 views
9

Hice un juego de blackjack, y quiero que el jugador de AI haga una pausa entre cartas. Intenté simplemente usar Thread.sleep (x), pero eso hace que se congele hasta que el jugador de AI termine de tomar todas sus cartas. Sé que Swing no es seguro para subprocesos, así que miré Timers, pero no pude entender cómo podría usar uno para esto. Aquí está mi código actual:Cómo crear un retraso en Swing

while (JB.total < 21) { 

      try { 
      Thread.sleep(1000); 
      } catch (InterruptedException ex) { 
      System.out.println("Oh noes!"); 
      } 

      switch (getJBTable(JB.total, JB.aces > 0)) { 
      case 0: 
       JB.hit(); 
       break; 
      case 1: 
       break done; 
      case 2: 
       JB.hit(); 
       JB.bet *= 2; 
       break done; 
      } 
     } 

BTW, the hit(); método actualiza la GUI.

Respuesta

3

Bueno, el siguiente código muestra un JFrame con un JTextArea y un JButton. Cuando se hace clic en los botones, el temporizador envía el evento repetidamente (con un segundo retraso entre ellos) al actionListener relacionado con el botón que agrega una línea con la hora actual.

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.Calendar; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JTextArea; 
import javax.swing.Timer; 


public class TimerTest extends JFrame implements ActionListener{ 

    private static final long serialVersionUID = 7416567620110237028L; 
    JTextArea area; 
    Timer timer; 
    int count; // Counts the number of sendings done by the timer 
    boolean running; // Indicates if the timer is started (true) or stopped (false) 

    public TimerTest() { 
     super("Test"); 
     setBounds(30,30,500,500); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 
     setLayout(null); 

     area = new JTextArea(); 
     area.setBounds(0, 0, 500, 400); 
     add(area); 

     JButton button = new JButton("Click Me!"); 
     button.addActionListener(this); 
     button.setBounds(200, 400, 100, 40); 
     add(button); 

     // Initialization of the timer. 1 second delay and this class as ActionListener 
     timer = new Timer(1000, this); 
     timer.setRepeats(true); // Send events until someone stops it 
     count = 0; // in the beginning, 0 events sended by timer 
     running = false; 
     System.out.println(timer.isRepeats()); 
     setVisible(true); // Shows the frame 
    } 

    public void actionPerformed(ActionEvent e) { 
     if (! running) { 
      timer.start(); 
      running = true; 
     } 
     // Writing the current time and increasing the cont times 
     area.append(Calendar.getInstance().getTime().toString()+"\n"); 
     count++; 
     if (count == 10) { 
      timer.stop(); 
      count = 0; 
      running = false; 
     } 
    } 

    public static void main(String[] args) { 
     // Executing the frame with its Timer 
     new TimerTest(); 
    } 
} 

Bueno, este código es una muestra de cómo usar objetos javax.swig.Timer. En relación con el caso particular de la pregunta. La instrucción if para detener el temporizador debe cambiar, y, obviamente, las acciones de la acción realizada.El siguiente fragmento es un esqueleto de la solución actionPerformed:

public void actionPerformed(ActionEvent e) { 
    if (e.getComponent() == myDealerComponent()) { 
    // I do this if statement because the actionPerformed can treat more components 
     if (! running) { 
      timer.start(); 
      runnig = true; 
     } 
     // Hit a card if it must be hitted 
     switch (getJBTable(JB.total, JB.aces > 0)) { 
      case 0: 
       JB.hit(); 
       break; 
      case 1: 
       break done; 
      case 2: 
       JB.hit(); 
       JB.bet *= 2; 
       break done; 
     } 
     if (JB.total >= 21) { // In this case we don't need count the number of times, only check the JB.total 21 reached 
      timer.stop() 
      running = false; 
     } 

    } 
} 

mi humilde opinión esto resuelve el problema, ahora @ user920769 hay que pensar en poner el actionListener y las condiciones de partida/parada ...

@kleopatra: Gracias para mostrarme la existencia de esta clase de temporizador, no sé nada al respecto y es increíble, hacer posible un montón de tareas en una aplicación de swing :)

+0

Muchas gracias por el ejemplo, pero me aparece un error en estas líneas: timer = new Timer (1000, this); timer.setRepeats (true); Diciendo que no puede encontrar el constructor o método adecuado, respectivamente. ¿Estaban obsoletos? – Fractaly

+0

¿Importas la clase Timer? Los métodos no están en desuso incluso en la última versión, por lo tanto, parece ser su error. [Aquí el ApiDoc de Java7] (http://download.oracle.com/javase/7/docs/api/javax/swing/Timer.html) – Charliemops

7

Así que miré a temporizadores, pero yo no podía entender cómo podía usar uno de éstos

El temporizador es la solución, ya que como usted dice que está actualizando la interfaz gráfica de usuario que debe hacerse en el EDT.

No estoy seguro de cuál es su preocupación. Usted reparte una carta y enciende el temporizador. Cuando el temporizador se dispara, decide tomar otra tarjeta o sostenerla. Cuando sostienes tu parada, el temporizador.

+0

gracias, pero podría darme un ejemplo de código para saber cómo usar un temporizador para esto? Lo intenté antes, y arrojó un error, olvidé lo que era exactamente. – Fractaly

+0

@ user920769 para ver (y leer cuidadosamente) el error nuevamente, intente de nuevo – kleopatra

3

Creo que en this tutorial está claro cómo usar los temporizadores para lograr lo que quiere, sin tener que lidiar con los hilos.

+1

esta respuesta es de la buena – alex

4

Bueno, una explicación rápida sobre temporizadores.

En primer lugar, necesita una variable java.util.Timer en su clase y otra clase en su proyecto que se extiende desde java.util.TimerTask (llamémoslo Tasker).

La inicialización de la variable temporizador es tan fácil:

Timer timer = new Timer(); 

Ahora la clase Tasker:

public class Tasker extends TimerTask { 
    @Override 
    public void run() { 
     actionToDo(); // For example take cards 
    } 

    // More functions if they are needed 
} 

Por último, la instalación del contador de tiempo con su relacionada Tasker:

long delay = 0L; 
long period = pauseTime; 
timer.schedule(new Tasker(),delay,period); 

La función de programación indica lo siguiente: Param de Fisrt: Acción para d o cada período de milisegundos (Ejecuta la función de ejecución de una clase TimerTask o su extensión) Segundo parámetro: cuando el temporizador debe comenzar. En este caso, comienza cuando se llama a la función de programación. El siguiente ejemplo indica un inicio de 1 segundo después de llamar a la función de programación: timer.schedule(new Tasker(),1000,period); Tercer parámetro: milisegundos entre una llamada de la función Tasker.run() y la siguiente llamada.

Espero que entiendas este microtutorial :). Si tiene algún problema, solicite información más detallada.

Saludos cordiales!

+0

(editado para eliminar el absolutismo :-) en realidad, rara vez usa una utilidad.Timer en Swing, en su lugar use swingx. Temporizador o (para tareas de fondo más complejas) SwingWorker – kleopatra

+0

@kleopatra 'swingx.Timer' (rasca la cabeza) DYM a' javax.swing.Timer'? No puedo decir que me he encontrado con el otro. –

+0

Bueno, puse el código con el utilitario.Timer porque es el que utilicé en un proyecto hace un año. Mi proyecto era un juego voleibol y usamos la estructura anterior para volver a calcular la información y actualizar la ventana cada 0,04 segundos. No sé cómo usar swingx.Timer, pero este código funciona correctamente en aplicaciones gráficas. No congela la ventana y permite que el usuario haga las cosas sin ningún problema. =) – Charliemops

Cuestiones relacionadas