2011-08-31 15 views
9

Stworzyłem grę w blackjacka i chcę, aby gracz AI zatrzymywał się pomiędzy przyjmowaniem kart. Próbowałem po prostu używać Thread.sleep (x), ale to powoduje, że zamarza, aż gracz AI skończy wszystkie swoje karty. Wiem, że Swing nie jest bezpieczny dla wątków, więc przyjrzałem się Timerom, ale nie mogłem zrozumieć, w jaki sposób mogę go wykorzystać. Oto mój obecny kod:Jak utworzyć opóźnienie w Swingu

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, hit(); metoda aktualizuje GUI.

Odpowiedz

3

Cóż, poniższy kod pokazuje JFrame z JTextArea i JButton. Po kliknięciu przycisków, licznik przesyła zdarzenie wielokrotnie (z drugim opóźnieniem między nimi) do parametru actionListener związanego z przyciskiem, który dodaje linię do bieżącego czasu.

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

Ten kod jest próbką użycia obiektów javax.swig.Timer. W odniesieniu do konkretnego przypadku pytania. Instrukcja if, aby zatrzymać stoper musi się zmienić, i oczywiście działania akcji zostały wykonane.Poniższy fragment jest szkielet rozwiązania 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 to rozwiąże problem, teraz @ user920769 musi myśleć gdzie umieścić ActionListener i/warunki WY¸ÑCZANIE Uruchamianie ...

@kleopatra: Dzięki dla pokazania mi istnienia tej klasy czasomierza, nic o niej nie wiem i to jest niesamowite, sprawić, że wiele zadań do aplikacji do swinga :)

+0

Dziękuję bardzo za przykład, ale dostaję błąd na tych liniach: timer = new Timer (1000, this); timer.setRepeats (true); Mówiąc, że nie może znaleźć odpowiedniego konstruktora lub metody, odpowiednio. Czy były przestarzałe? – Fractaly

+0

Czy importujesz klasę Timer? Metody nie są przestarzałe nawet w ostatnim wydaniu, dlatego wydaje się, że popełniłeś błąd. [Tutaj apiDoc Java7] (http://download.oracle.com/javase/7/docs/api/javax/swing/Timer.html) – Charliemops

7

tak patrzyłem na liczniki, ale nie mogłem zrozumieć, w jaki sposób mogę skorzystać z jednej do tego

czasomierz jest rozwiązaniem, ponieważ jak mówisz aktualizujesz GUI, które powinny być wykonane na EDT.

Nie jestem pewien, co to jest. Rozdajesz kartę i uruchamiasz programator. Po uruchomieniu Timera decydujesz się na wzięcie kolejnej karty lub przytrzymanie. Kiedy zatrzymasz stoper.

+0

dziękuję, ale mógłbyś podać mi przykładowy kod jak używać do tego timera? Próbowałem wcześniej, a to spowodowało błąd, zapomniałem, co jest dokładnie. – Fractaly

+0

@ user920769, aby zobaczyć (i uważnie przeczytać;) błąd ponownie, spróbuj ponownie – kleopatra

3

Myślę, że w this tutorial jest jasne, jak używać Timerów, aby osiągnąć to, co chcesz, bez konieczności zajmowania się wątkami.

+1

esta respuesta es de la buena – alex

4

Cóż, szybkie wyjaśnienie dotyczące timerów.

Przede wszystkim potrzebna jest zmienna java.util.Timer w klasie i inna klasa w projekcie, która rozciąga się od java.util.TimerTask (nazwijmy to Tasker).

Inicjalizacja zmiennej timera jest tak proste:

Timer timer = new Timer(); 

Teraz klasa Tasker:

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

    // More functions if they are needed 
} 

Wreszcie instalacja zegar z powiązanej Tasker:

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

Funkcja harmonogramu wskazuje: Fisrt param: Akcja d o każdy okres milisekund (wykonuje funkcję run klasy TimerTask lub jej rozszerzenie) Drugi parametr: Kiedy timer musi się uruchomić. W takim przypadku rozpoczyna się po wywołaniu funkcji harmonogramu. Poniższy przykład wskazuje na uruchomienie 1 sekundy po wywołaniu funkcji harmonogramu: timer.schedule(new Tasker(),1000,period); Trzeci parametr: milisekundy między jednym wywołaniem funkcji Tasker.run() a następującym wywołaniem.

Mam nadzieję, że rozumiesz tę mikrotutorial :). Jeśli masz jakiś problem, poproś o bardziej szczegółowe informacje!

Pozdrawiam!

+0

(edytowane, aby usunąć absolutyzm :-) faktycznie - rzadko korzystasz z util.Timer w Swing, zamiast tego użyj swingx. Timer lub (w przypadku bardziej złożonych zadań w tle) SwingWorker – kleopatra

+0

@kleopatra 'swingx.Timer' (head scratch) DYM a' javax.swing.Timer'? Nie mogę powiedzieć, że spotkałem tego drugiego. –

+0

Cóż, umieściłem kod z util.Timer ponieważ jest to, którego użyłem w projekcie rok temu. Mój projekt był grą voleyball i używamy powyższej struktury do przeliczania informacji i odświeżania okna co 0,04 sekundy. Nie wiem, jak używać swingx.Timer, ale ten kod działa poprawnie w aplikacjach graficznych. Nie blokuje okna i pozwala użytkownikowi bez problemu robić wszystko. =) – Charliemops