JAVA non esegue una riga di codice, in gioco Memory

di il
4 risposte

JAVA non esegue una riga di codice, in gioco Memory

Ciao a tutti!
Sto creando il gioco memory, ma sto avendo un problema, cioè:
quando vengono cliccate due carte diverse, la seconda carta si deve girare, cioè mostrare il simbolo, aspettare per qualche secondo in questa posizione e poi ritornare a mostrare il retro della carta.
Il mio problema consiste che la carta non si gira e non mostra il simbolo, ma aspetta ugualmente 5 secondi per come specificato nel sottoprogramma tempo(), a livello di codice non esegue una riga.

Cattura.PNG
Cattura.PNG

Se commento la chiamata al sottoprogramma tempo() e la riga sotto questa chiamata, la carta si gira è mostra la figura.

Ora posto il codice del sottoprogramma tempo.
Cattura4.PNG
Cattura4.PNG

Probabilmente il problema è nel sottoprogramma tempo(), come da figura, uso: Thread.sleep(5000); ho cercato su internet, ma solo questo metodo mi funziona.

In caso qualcosa non sia chiaro, posto l'intero progetto o file.
Spero in un vostro aiuto.
Grazie mille a tutti

4 Risposte

  • Re: JAVA non esegue una riga di codice, in gioco Memory

    Prova ad inserire prima della sleep una chiamata a

    Thread.yield();
  • Re: JAVA non esegue una riga di codice, in gioco Memory

    angelo96 ha scritto:


    Il mio problema consiste che la carta non si gira e non mostra il simbolo, ma aspetta ugualmente 5 secondi per come specificato nel sottoprogramma tempo(), a livello di codice non esegue una riga.
    Nota innanzitutto che Thread.yield() NON ti serve e non ti garantisce un bel niente.

    La questione/problematica è la "solita" che si incontra in questi casi, ovvero il "threading" (cioè come funzionano i thread) nelle interfacce grafiche.

    Swing, come tanti altri framework grafici anche su altre piattaforme (e anche non Java), è single-thread. La tua applicazione può avere quanti thread eventualmente ti servono ma per la gestione della interfaccia grafica esiste un singolo e UNICO thread che in AWT/Swing è chiamato convenzionalmente EDT (Event Dispatch Thread).
    Questo thread è creato e gestito dal framework in modo automatico, non devi fare nulla in tal senso. Il EDT si occupa di svariati compiti, tra cui i più importanti: disegnare i componenti Swing e dispacciare gli eventi ai listener.

    Ma è chiaro che essendo un singolo thread, o sta facendo una cosa o ne sta facendo un'altra. Se il framework invoca un actionPerformed per un evento, quello che tu fai sui componenti in quel contesto es. p1.setText("...") o l1.setIcon( ... ) o altri set/add/ecc... il risultato a livello visuale NON avviene subito. I componenti determinano se/dove/come ridisegnare il componente e poi tipicamente fanno la richiesta di un repaint "asincrono", che viene depositata nella "coda" degli eventi.
    Il controllo DEVE ritornare al framework il prima possibile. Quindi actionPerformed deve terminare e il controllo poi ritorna al framework che in brevissimo tempo si accorgerà che nella coda c'è "un evento di repaint" da eseguire e quindi scatenerà tutta la logica di painting del/i componente/i coinvolto/i.

    Quindi il succo è che se nel contesto di un actionPerformed (o altro evento) fai uno sleep o qualunque operazione "lunga" (accesso al file-system, query su DB o altro potenzialmente pesante), stai tenendo "impegnato" tu il EDT e quindi la tua interfaccia grafica è completamente "congelata". Nessun componente può essere aggiornato e nessun altro evento può essere dispacciato.

    Swing funziona così. Hai una sola soluzione: comprendere BENE e in modo APPROFONDITO quanto ho detto e l'argomento in generale. Se non lo fai, te lo dico sinceramente, avrai SEMPRE problemi di questo tipo con le interfacce grafiche (Java/Swing ma anche in generale).
  • Re: JAVA non esegue una riga di codice, in gioco Memory

    Grazie mille della tempestiva risposta ad entrambi.
    Per andbin, ho capito il concetto!
    Però ora mi sorge una domanda, come potrei raggirare tale problema?
    Cosa ne pensi se uso il timer di Swing? Ho letto su internet che dovrebbe essere una possibile soluzione, solo che non sono riuscito ad implementarlo correttamente per il mio problema.
    Hai qualche consiglio di come posso usarlo?
    O hai qualche altro tipo di consiglio da darmi per risolvere?
    Grazie mille
  • Re: JAVA non esegue una riga di codice, in gioco Memory

    angelo96 ha scritto:


    Per andbin, ho capito il concetto!
    Dovrai comunque approfondire.

    angelo96 ha scritto:


    Però ora mi sorge una domanda, come potrei raggirare tale problema?
    Cosa ne pensi se uso il timer di Swing? Ho letto su internet che dovrebbe essere una possibile soluzione, solo che non sono riuscito ad implementarlo correttamente per il mio problema.
    Hai qualche consiglio di come posso usarlo?
    Sì, javax.swing.Timer è la soluzione più semplice. Crei un Timer con il delay voluto e una implementazione di ActionListener che imposta la 2° icona. Il Timer lo puoi rendere "one-shot" (un evento solo) con setRepeats(false).

    Poi dove prima facevi quei setIcon: prima imposti la 1° icona, poi invece di fare lo sleep (che come hai capito, NON va bene), fai lo start() sul Timer e la cosa per il momento termina lì. Quando arriverà l'evento del timer, quel ActionListener detto prima imposterà la 2° icona. Come vedi va tutto avanti "per eventi".
Devi accedere o registrarti per scrivere nel forum
4 risposte