2012-12-14 14 views
6

Sono nuovo nello swing, ogni aiuto è apprezzato.Aggiornamento componenti swing correttamente?

In questo pezzo di codice sto girando una carta a faccia in su, se risulta che non corrispondono, voglio che girino nuovamente a faccia in giù.

Al momento ciò che sta accadendo: 1. se cliccato la prima carta gira 2. quando una seconda scheda si fa clic su una delle due cose accadono (a) se sono la stessa entrambi rimanere sempre che è cosa voglio (b) se non sono gli stessi, non vedo mai la seconda carta perché rivisita immediatamente il retro della carta (e il retro della carta precedente anche come definito nel mio metodo).

Ho pensato di inserire il timer di sospensione per mantenere la seconda scheda visualizzata per un periodo di tempo prima di tornare indietro ma non è così.

Ho tentato di utilizzare contentPane.revalidate(); & contentPane.repaint(); ma non cambia nulla.

ho messo in alcune uscite per console:

Console output: 
Card: 0 set 
Card: 6 set 
Sleeping now 
Card: 6 unset 
Card: 0 unset 

sopra è l'uscita della console risultante quando si clicca due carte che non corrispondono

@Override 
public void actionPerformed(ActionEvent e) 
{ 
    String buttonPressed = e.getActionCommand(); 
    int pos = Integer.valueOf(buttonPressed); 
    action = Control.model.ReceiveCardsTurned(pos); 

    keypadArray[pos].setIcon(myIcons[pos]);  
    System.out.println("Card: "+pos+" set"); 
    currentTime.setText("" + Control.model.time); 
    currentScore.setText("" + Control.model.score); 

    //contentPane.revalidate(); 
    //contentPane.repaint();   

    if(Control.model.twoCardsTurned == false) 
    { 
     if (action == "unturn") 
     { 
      System.out.println("Sleeping now"); 

      try 
      { 
       Thread.sleep(1000); 
      } 

      catch (InterruptedException e1) 
      { 
       e1.printStackTrace(); 
      } 

      keypadArray[pos].setIcon(back); 
      keypadArray[Control.model.lastCard].setIcon(back); 
      System.out.println("Card: "+pos+" unset"); 
      System.out.println("Card: "+Control.model.lastCard+" unset"); 
     } 
    } 
} 

risposta

6

Ci sono alcuni concetti importanti che sembrano mancare.

  1. L'oscillazione è un ambiente guidato da eventi. Ciò significa che non ci sono mezzi (o almeno solo pochissimi) che puoi "aspettare" per l'input dell'utente, in genere, devi solo reagire alla loro interazione.
  2. L'oscillazione è determinata da un singolo thread, noto come Thread di invio eventi (AKA EDT). È responsabilità di questo thread inviare/elaborare gli eventi che arrivano nell'applicazione alle parti appropriate dell'applicazione in modo che possano agire.
  3. Il gestore di ridisposizione invia le sue richieste di aggiornamento all'EDT.

QUALSIASI azione da intraprendere che impedisca a EDT di eseguire questo lavoro renderà l'applicazione come se fosse appesa.

Non è MAI necessario eseguire operazioni che richiedono tempo (ad esempio I/O, loop o Thread#sleep per l'EDT), in tal modo si renderà l'applicazione "in pausa", che non è mai carina.

Leggere il numero Concurrency in Swing per ulteriori informazioni.

Ora avete un numero di scelte. È possibile utilizzare uno Thread per "attendere" in background e riaccendere le schede oppure è possibile utilizzare uno SwingWorker o uno javax.swing.Timer.

L'altro problema che si ha è che non si deve MAI aggiornare alcun componente dell'interfaccia utente da qualsiasi Thread diverso dall'EDT.Questo significa che se si dovesse usare un Thread, si diventerebbe responsabili per risincronizzare quel thread con EDT. Anche se non è difficile, diventa solo disordinato.

SwingWorker e javax.swing.Timer hanno funzionalità che rendono questo molto più facile.

I thread e SwingWorker sono ottimi per eseguire l'elaborazione in background e sarebbero semplicemente eccessivi per questo problema. Invece, un javax.swing.Timer si adatterebbe perfettamente qui.

if (!Control.model.twoCardsTurned) 
    { 
     if ("unturn".equals(action)) 
     { 
      new Timer(1000, new ActionListener() { 
       public void actionPerformed(ActionEvent evt) { 
        keypadArray[pos].setIcon(back); 
        keypadArray[Control.model.lastCard].setIcon(back); 
        System.out.println("Card: "+pos+" unset"); 
        System.out.println("Card: "+Control.model.lastCard+" unset"); 
       } 
      }).start(); 
     } 
    } 

Questo è un esempio molto semplice. Potresti inserire alcuni controlli che impediscono all'utente di fare clic su qualsiasi cosa fino a quando il timer non scatta, ad esempio;)

+0

Grazie ancora, molto risposta utile e molto informativa. Dovrò fare ancora un po 'di lettura sui concetti base dello swing – Ron

7

Non si può dormire in thread evento dispatch , perché la tua GUI si bloccherà. Devi usare Swing Timer. Per le attività in background di cui probabilmente dovrai preoccuparti in futuro, dai uno sguardo allo SwingWorker.

+0

@HovercraftFullOfEels Ho migliorato la risposta, grazie per la nota. – Behnil

+0

Sono d'accordo con Hovercraft, penso che 'SwingWorker' è sopra uccidere per questo semplice problema – MadProgrammer

+0

Grazie per il tuo aiuto amico – Ron

Problemi correlati