2011-08-31 10 views
9

Ho fatto un gioco di blackjack e voglio che il giocatore di IA si fermi tra le carte. Ho provato semplicemente a usare Thread.sleep (x), ma ciò lo rende fermo fino a quando il giocatore di IA non ha completato tutte le sue carte. So che Swing non è thread-safe, quindi ho guardato Timers, ma non riuscivo a capire come potrei usarne uno per questo. Ecco il mio codice corrente:Come creare un ritardo in 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, il colpo(); metodo aggiorna la GUI.

risposta

3

Bene, il codice seguente mostra un JFrame con JTextArea e un JButton. Quando si fa clic sui pulsanti, il Timer invia l'evento ripetutamente (con un secondo ritardo tra di loro) all'actionListener relativo al pulsante che accoda una linea con l'ora corrente.

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(); 
    } 
} 

Bene, questo codice è un esempio di come utilizzare gli oggetti javax.swig.Timer. In relazione al caso particolare della domanda. L'istruzione if per fermare il timer deve cambiare e, ovviamente, le azioni dell'actionPerformed.Il seguente frammento è uno scheletro della soluzione 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; 
     } 

    } 
} 

IMHO ciò risolve il problema, ora @ user920769 deve pensare dove mettere l'ActionListener e le condizioni di partenza/arresto ...

@kleopatra: Grazie per avermi mostrato l'esistenza di questa classe di timer, non ne so nulla ed è incredibile, rendere possibili molte cose con compiti in un'applicazione swing :)

+0

Grazie mille per l'esempio, ma sto ricevendo un errore su queste righe: timer = new Timer (1000, this); timer.setRepeats (true); Dicendo che non può trovare il costruttore o il metodo adatto, rispettivamente. Erano deprecati? – Fractaly

+0

Importa la classe Timer? I metodi non sono deprecati anche nell'ultima versione, quindi sembra un tuo errore. [Qui Java ApiDoc] (http://download.oracle.com/javase/7/docs/api/javax/swing/Timer.html) – Charliemops

7

Così ho guardato timer, ma non riuscivo a capire come ho potuto utilizzare uno per questo

Il timer è la soluzione, dal momento che come dici tu si sta aggiornando l'interfaccia grafica che dovrebbe essere fatto su l'EDT.

Non sono sicuro di quale sia la vostra preoccupazione. Ti occupi di una carta e avvia il timer. Quando il timer scocca, decidi di prendere un'altra carta o tenerla. Quando tieni fermo il timer.

+0

grazie, ma potrei semplicemente darmi qualche esempio di codice per come usare un timer per questo? Ho provato prima, e ha gettato un errore, ho dimenticato cosa è stato esattamente. – Fractaly

+0

@ user920769 per vedere (e leggere attentamente;) l'errore di nuovo, riprovare – kleopatra

3

Penso che in this tutorial sia chiaro come utilizzare i timer per ottenere ciò che si desidera, senza dover trattare con i thread.

+1

esta respuesta es de la buena – alex

4

Bene, una rapida spiegazione su Timer.

Prima di tutto, è necessaria una variabile java.util.Timer nella classe e un'altra classe nel progetto che si estende da java.util.TimerTask (chiamiamolo Tasker).

L'inizializzazione della variabile Timer è così facile:

Timer timer = new Timer(); 

Ora la classe Tasker:

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

    // More functions if they are needed 
} 

Infine, l'installazione del timer con il suo Tasker correlato:

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

La funzione di programmazione indica quanto segue: Param Parama: azione per d o ogni millisecondo di periodo (Esegue la funzione di esecuzione di una classe TimerTask o la sua estensione) Secondo parametro: quando il timer deve iniziare. In questo caso, inizia quando viene chiamata la funzione di pianificazione. L'esempio seguente indica un avvio 1 secondo dopo la chiamata della funzione di pianificazione: timer.schedule(new Tasker(),1000,period); Terzo parametro: millisecondi tra una chiamata della funzione Tasker.run() e la seguente chiamata.

Spero che tu abbia capito questo microtutorial :). Se hai qualche problema, chiedi informazioni più dettagliate!

Cordiali saluti!

+0

(modificato per rimuovere l'assolutismo :-) in realtà - raramente usi un util.Timer in Swing, invece usa swingx. Timer o (per attività di background più complesse) SwingWorker – kleopatra

+0

@kleopatra 'swingx.Timer' (graffia testa) DYM a' javax.swing.Timer'? Non posso dire di aver incontrato l'altro. –

+0

Bene, ho messo il codice con l'util.Timer perché è quello che ho usato in un progetto un anno fa. Il mio progetto era un gioco di voleyball e usiamo la struttura sopra descritta per ricalcolare le informazioni e aggiornare la finestra ogni 0,04 secondi. Non so come usare swingx.Timer, ma questo codice funziona correttamente in applicazioni grafiche. Non blocca la finestra e lascia che l'utente faccia le cose senza problemi. =) – Charliemops

Problemi correlati