2011-09-28 9 views
7

Tworzę grę Pamięć, kiedy wybierasz dwie karty, a jeśli pasują, to je zatrzymaj, w przeciwnym razie odrzuć je. Jeśli pamiętasz karty, które już wybrałeś, możesz zaryzykować lepsze przypuszczenie na temat dwóch następnych kart.Jak wywołać natychmiastową aktualizację interfejsu GUI Java? (konflikt z Thread.sleep())

Problem, który mam, polega na tym, że metoda repaint() nie wymaga natychmiastowego malowania.

Kiedy przerzucam drugą kartę, niezależnie od wyniku, chcę pokazać obie karty odwrócone prawą stroną przed odrzuceniem lub odrzuceniem. Robię to pod numerem sleep().

Oczywiście, jeśli I repaint() karty, aby odwrócić je prawą stroną do góry, odczekaj chwilę, a następnie repaint() ponownie w oparciu o ich wartości, pomocne małe Java będzie tylko odświeżyć raz (Tęsknię za C!).

Zasadniczo chcę wymusić aktualizację przed I sleep(). Czytałem inne wątki, które zasadniczo mówią, że najlepszym sposobem jest stworzenie dwóch wątków, aby zachować logikę i grafikę osobno, a następnie można sleep() logiki i zachować aktualizację GUI, ale jestem w pierwszym semestrze pierwszego roku CS Oczywiście w liceum, i chciałbym utrzymać go na poziomie kursu (chociaż spędziłem sporo czasu nad tworzeniem i kodowaniem w C).

Ponieważ znam pomocnych ludzi w miłości do StackOverflow do czytania kodu, oto część programu, o której mówię poniżej. Klasa HitArea jest obiektem Card, a tablica cards[] zawiera liczbę HitArea (nie zmieniłem nazwy klasy HitArea). activeCard1 i są to instancje HitArea używane do śledzenia dwóch wyborów użytkownika, a pusty konstruktor jest zarezerwowanym "niewidocznym" HitArea, chociaż zmienię go później na wartość null. Ostatecznie, cards.flip() odwraca wartość logiczną, która określa, czy karta jest prawą stroną do góry.

public void respond(HitArea choice) 
{ 
    if(choice.inGame) 
    { 
     if(activeCard1.value == 0 && activeCard1.value == 0) 
      activeCard1 = choice; 
     else if((!(activeCard1.value == 0) && activeCard2.value == 0) && (activeCard1.id != choice.id)) 
     { 
      activeCard2 = choice; 
      check(); 
     } 

    } 
} 
public void check() 
{ 
    update(); 
    pause(250); 
    if(activeCard2.value == activeCard1.value) 
    { 
     score += 2; 
     activeCard1.inGame = false; 
     activeCard2.inGame = false; 
    } 
    activeCard1.flip(); 
    activeCard2.flip(); 
    activeCard1 = new HitArea(); 
    activeCard2 = new HitArea(); 
} 
public void pause(int milliseconds) 
{ 
    try{ 
     Thread.currentThread().sleep(milliseconds); 
    } 
    catch(InterruptedException e){ 
     System.out.println("Exception: " + e); 
    } 
} 

public void mousePressed(MouseEvent e) 
{ 
    int x = e.getX(); 
    int y = e.getY(); 

    for (int i = 0; i < cardNum; i++) 
     if(cards[i].boundsCheck(x, y)) 
     { 
      repaint(); 
      cards[i].flip(); 
      respond(cards[i]); 
     } 
} 

Nie mam wątpliwości, że w moim kodzie są pewne problemy, dlatego warto je wskazać. Myślę, że moja podstawowa struktura jest w porządku i wolałbym nie tworzyć wielu wątków dla tego projektu (pamiętaj, to jest proste!).

Odpowiedz

14

Nie wywoływać Thread.sleep (...) na głównym gwincie Swing, EDT. Ever. Zamiast tego użyj Swing Timer.

Rozważ użycie JLabels do wyświetlenia obrazów, a następnie możesz "odwrócić" swoje karty, po prostu zamieniając ImageIcons. Po odwróceniu drugiej karty, jeśli jej nie ma, uruchom nie powtarzający się licznik Swing z opóźnieniem xxxx ms, aw metodzie actionCommand metody ActionListener odwraca oba JLabel z powrotem do domyślnego ImageIcon.

javax.swing.Timer poradnik można znaleźć tutaj: How to use Swing Timers

Edit:
chodzi o komentarz na temat korzystania g.drawString: to teraz jeszcze prostsze, ponieważ wszystko, co musisz zrobić, to zamiana na swoje Tekst JLabel. Ale później, jeśli zdecydujesz się na uaktualnienie programu do wyświetlania obrazów, masz wszystko ustawione, aby to zrobić.

Edit 2:
Jeśli chodzi o Twoje pytanie na temat tworzenia nowej klasy ActionListener: użyję anonimową klasę wewnętrzną do tego. Na przykład:

int delayTime = 2 * 1000; 
    javax.swing.Timer myTimer = new Timer(delayTime, new ActionListener() { 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     // TODO: put in the code you want called in xxx mSecs. 
    } 
    }); 
    myTimer.setRepeats(false); 
    myTimer.start(); 
+3

Chciałbym pogrubić i pochylić "Zawsze". :) – fireshadow52

+0

Po prostu wyświetlam trochę tekstu g.drawString (...), żadnych obrazów. Czy to samo dotyczy? –

+0

Dzięki, i gotowe. :) –