2011-09-28 5 views
7

Sto facendo il gioco Memory, quando prendi due carte e se corrispondono si arriva a tenerle, altrimenti le si torna indietro. Se poi ricordi le carte che hai già scelto, puoi provare a indovinare meglio le prossime due carte.Come si richiama un aggiornamento immediato a una GUI Java? (conflitto con Thread.sleep())

Il problema che riguarda il metodo repaint() non viene immediatamente ridipinto.

Quando lancio la seconda carta, non importa il risultato, voglio mostrare entrambe le carte ruotate con il lato destro in alto prima di scartarle o ribaltarle. Lo faccio chiamando lo sleep().

Ovviamente se I repaint() le carte per capovolgerle con il lato destro verso l'alto, attendere un secondo, e quindi repaint() di nuovo in base ai loro valori, utile piccolo Java si ridipinge solo una volta (mi manca C!).

In pratica, desidero forzare il richiamo di un aggiornamento prima di I sleep(). Ho letto alcuni altri thread che fondamentalmente dicono che il modo migliore è quello di creare due thread per mantenere la logica e la grafica separate, e quindi è possibile sleep() la logica e mantenere la vostra GUI di aggiornamento, ma io sono nel primo semestre di un primo anno CS corso al liceo, e vorrei mantenerlo sul livello del corso (anche se ho trascorso un po 'di tempo nel corso dello sviluppo del Web estivo e della codifica in C).

Perché so che le persone utili su StackOverflow amano leggere il codice, ecco la parte del programma a cui mi riferisco di seguito. La classe HitArea è l'oggetto Card e l'array cards[] contiene un numero di HitArea (non è stato possibile rinominare la classe HitArea). activeCard1 e activeCard2 sono HitArea istanze che uso per tenere traccia delle due selezioni dell'utente e il costruttore vuoto è un "invisibile" riservato HitArea, anche se lo cambierò in null successivamente. Infine, cards.flip() inverte un valore booleano toggle che determina se la scheda è rivolta verso destra.

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

Non ho dubbi che ci siano alcuni problemi nel mio codice, quindi sentitevi liberi di indicarli. Penso che la mia struttura di base sia a posto, e preferirei non creare più thread per questo progetto (ricorda, è fondamentale!).

risposta

14

Non chiamare Thread.sleep (...) sul thread Swing principale, EDT. Sempre. Usa invece un timer Swing.

Considerare l'utilizzo di JLabels per visualizzare le immagini e quindi è possibile "capovolgere" le carte semplicemente scambiando ImageIcons. Quando la seconda scheda è stata girata, se non c'è corrispondenza, avvia un timer di swing non ripetuto con un ritardo per xxxx ms, e nel metodo actionCommand di ActionListener del timer, fa in modo che entrambe le JLabel tornino all'ImageIcon predefinito.

Il javax.swing.Timer tutorial può essere trovato qui: How to use Swing Timers

Edit:
Per quanto riguarda i suoi commenti su come utilizzare g.drawString: è ancora più facile ora, poiché tutto ciò che dovete fare è scambiare la vostra Il testo di JLabel. Ma più tardi se decidi di aggiornare il programma per visualizzare le immagini, hai tutto pronto per farlo.

Edit 2:
quanto riguarda la tua domanda di fare una nuova classe ActionListener: mi piacerebbe utilizzare una classe interna anonima per questo. Ad esempio:

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

Vorrei grassetto e in corsivo "Ever". :) – fireshadow52

+0

Sto solo mostrando del testo g.drawString (...), senza immagini. Lo stesso varrebbe? –

+0

Grazie, e fatto. :) –