Torna indietro   Hardware Upgrade Forum > Software > Programmazione

DJI Osmo Mobile 8: lo stabilizzatore per smartphone con tracking multiplo e asta telescopica
DJI Osmo Mobile 8: lo stabilizzatore per smartphone con tracking multiplo e asta telescopica
Il nuovo gimbal mobile DJI evolve il concetto di tracciamento automatico con tre modalità diverse, un modulo multifunzionale con illuminazione integrata e controlli gestuali avanzati. Nel gimbal è anche presente un'asta telescopica da 215 mm con treppiede integrato, per un prodotto completo per content creator di ogni livello
Recensione Pura 80 Pro: HUAWEI torna a stupire con foto spettacolari e ricarica superveloce
Recensione Pura 80 Pro: HUAWEI torna a stupire con foto spettacolari e ricarica superveloce
Abbiamo provato il nuovo HUAWEI Pura 80 Pro. Parliamo di uno smartphone che è un vero capolavoro di fotografia mobile, grazie ad un comparto completo in tutto e per tutto, In questa colorazione ci è piaciuto molto, ma i limiti hardware e software, seppur in netto miglioramento, ci sono ancora. Ma HUAWEI ha fatto davvero passi da gigante per questa nuova serie Pura 80. Buona anche l'autonomia e soprattutto la ricarica rapida sia cablata che wireless, velocissima.
Opera Neon: il browser AI agentico di nuova generazione
Opera Neon: il browser AI agentico di nuova generazione
Abbiamo provato il nuovo web browser con intelligenza artificiale della serie Opera accessibile tramite abbonamento. Ecco le nostre prime impressioni sulle funzionalità di Opera Neon basate su AI e come funzionano
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 21-01-2013, 14:48   #1
Groove89
Member
 
Iscritto dal: Jul 2006
Messaggi: 206
[JAVA] Aiutino con Swing e Threads

Mi appello agli utenti che hanno partecipato a questa discussione:
http://www.hwupgrade.it/forum/showthread.php?t=2038842
Mi sembrano abbastanza esperti nell'argomento e credo che possano aiutarmi.
Il discorso mi è stato molto utile ma siccome necessito di accelerare i tempi
non posso approfondire da solo l'argomento ed ho bisogno di qualche consiglio
pratico per il mio caso che è un po più articolato.
Cerco di farla breve. Sto creando il gioco briscola con interfaccia grafica.
Ogni volta che l'utente gioca (clicca sulla carta) ovviamente c'è la logica
che fa i suoi calcoli e la grafica che si aggiorna. Ho problemi tecnici con
l'aggiornamento della grafica. Sfruttando gli esempi postati nella discussione
che ho linkato ho scritto questo ascoltatore per i pulsanti (le carte) del
giocatore umano:

Codice:
package gui;

import gui.GuiPartita;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.SwingUtilities;
import singleplayer.Partita;

public class MyListenerGiocatore implements ActionListener {

	private GuiPartita gp;
	private Partita p;
	
	public MyListenerGiocatore(GuiPartita gp, Partita p) {
		this.gp = gp;
		this.p = p;
	}
	
	public void actionPerformed(ActionEvent event) {
		computazione(gp,event);
	}
	
	private void computazione(final GuiPartita gp, final ActionEvent e) 
	{
	    Runnable computazione = new Runnable() {
	        @Override
	        public void run() {

	        	//calcolo
	        	if(e.getSource().equals(gp.primaCartaGiocatore)) {
	    			System.out.println("Il giocatore gioca la carta: " + p.getGiocatore().getPrimaCarta() + "\n");
	    			p.setStato(1);
	    			p.interfacciamentoUtente(1);
	    		}
	    		
	    		if(e.getSource().equals(gp.secondaCartaGiocatore)) {
	    			System.out.println("Il giocatore gioca la carta: " + p.getGiocatore().getSecondaCarta() + "\n");
	    			p.setStato(1);
	    			p.interfacciamentoUtente(2);
	    		}
	    		
	    		if(e.getSource().equals(gp.terzaCartaGiocatore)) {
	    			System.out.println("Il giocatore gioca la carta: " + p.getGiocatore().getTerzaCarta() + "\n");
	    			p.setStato(1);
	    			p.interfacciamentoUtente(3);
	    		}

	            // qui ha finito: accoda evento grafico
	            SwingUtilities.invokeLater(new Runnable()
	            {
	                @Override
	                public void run() {
	                	gp.aggiornaGrafica(); 
	                	gp.repaint();
	                }
	            });
	        }
	    };
	    (new Thread(computazione)).start();
	}
}
Ovviamente non basta perché così facendo la grafica si aggiorna
correttamente solo quando è l'umano a giocare. Deve aggiornarsi anche
quando è il computer a giocare e lo fa in automatico. Come risolvo questo
piccolo problema?
C'è anche il caso particolare della fine della partita. Da qualche parte
devo controllare se la partita è ancora in corso, e se finisce aprire una
nuova finestra che mostra il risultato. Può essere un'azione svolta in
background utilizzando un worker thread? Vi prego un piccolo aiuto, grazie

Ultima modifica di Groove89 : 23-01-2013 alle 09:11.
Groove89 è offline   Rispondi citando il messaggio o parte di esso
Old 22-01-2013, 16:38   #2
Groove89
Member
 
Iscritto dal: Jul 2006
Messaggi: 206
Ok la discussione ha spaventato
Facciamo così, cerco di essere molto più specifico.
Logica --> classe Partita.
Grafica --> classe GuiPartita.
GuiPartita prende un'istanza di Partita nel costruttore.

Il "motore" della logica che muove il tutto è dato da questo codice presente nella classe Partita:

Codice:
private void start() {
		
		/* Controlla turno e stato del gioco dell'utente
         * e si ramifica in 4 possibili situazioni
         */
		
        /* turno PC */
        if(isTurnoPc()) {
            /* user non ha giocato (inizio della mano) */
            if(!userHavePlayed) {
                giocoPcScarta();
                System.out.println("E' il turno del giocatore.\n");
            }
            /*user ha già risposto al gioco pc: calcolo punti e vincitore*/
            else {
                fineMano();
            }
        }
        
        /* turno user */
        else {
            /* user non ha giocato (inizio della mano) */
            if(!userHavePlayed) {
                /* non accade nulla
                 * serve il gioco dell'utente
                 */        
            }
            
            /* user ha giocato e attende risposta pc */
            else {
                giocoPcRisposta();   /* risposta pc */
                fineMano();          /* punti e vincitore */
            }            
        }
    }
L'idea che mi è venuta in mente poco fa per aggiornare la grafica di volta in volta è inserire nella classe partita una variabile stato che può assumere i
valori 0,1,2,3,4,5.

Stato 0 = Sta iniziando la nuova mano.
Stato 1 = Ha giocato il computer.
Stato 2 = Hanno giocato sia computer che giocatore. Prima il computer e poi
il giocatore.
Stato 3 = Il giocatore ha giocato.
Stato 4 = Hanno giocato sia computer che giocatore. Prima il giocatore e poi
il computer.
Stato 5 = Fine della partita.

Per aggiornare lo stato di volta in volta prenderei il codice di sopra e lo
modificherei così:

Codice:
private void start() {
	stato = 0;
		/* Controlla turno e stato del gioco dell'utente
         * e si ramifica in 4 possibili situazioni
         */
		
        /* turno PC */
        if(isTurnoPc()) {
            /* user non ha giocato (inizio della mano) */
            if(!userHavePlayed) {
                giocoPcScarta();
                stato = 1;
                System.out.println("E' il turno del giocatore.\n");
            }
            /*user ha già risposto al gioco pc: calcolo punti e vincitore*/
            else {
                fineMano();
                stato = 2;
            }
        }
        
        /* turno user */
        else {
            /* user non ha giocato (inizio della mano) */
            if(!userHavePlayed) {
                /* non accade nulla
                 * serve il gioco dell'utente
                 */        
            }
            stato = 3;
            /* user ha giocato e attende risposta pc */
            else {
                giocoPcRisposta();   /* risposta pc */
                fineMano();          /* punti e vincitore */
                stato = 4;
            }            
        }
    }
Ovviamente nella medesima classe inserisco il metodo get per lo stato.

La grafica deve poter controllare ciclicamente lo stato della Partita
e vedere in che stato si trova. Questo deve avvenire senza bloccare
la grafica, quindi usando edt o worker thread o non so cosa xD.

Farei una cosa del tipo (non so come e dove):

Codice:
	public void checkPartita() {
		while(partita.inPartita()) {
			if(stato == 0) {
				aggiornaGrafica0();
			}
			if(stato == 1) {
				aggiornaGrafica1();
			}
			if(stato == 2) {
				aggiornaGrafica2();
			}
			if(stato == 3) {
				aggiornaGrafica3();
			}
			if(stato == 4) {
				aggiornaGrafica4();
			}
			if(stato == 5) {
				aggiornaGrafica5;
			}
		}
	}
Potrebbe andar bene? Consigli o botte per me?
Groove89 è offline   Rispondi citando il messaggio o parte di esso
Old 22-01-2013, 22:27   #3
wingman87
Senior Member
 
Iscritto dal: Nov 2005
Messaggi: 2780
Botte.

No scherzo, ma non capisco esattamente qual è il problema. Senza entrare nel dettaglio, nel primo post hai scritto che riesci ad aggiornare la grafica quando è il giocatore a giocare ma non quando è il computer... non capisco perché.
Vedendo il secondo post sembra che non sai quando dire al computer: "gioca tu". Beh, è semplice, dopo che il giocatore ha giocato no? D'altra parte dal codice che hai scritto è chiaro che il computer gioca if(userHavePlayed).

Se invece inizia a giocare il computer, farà la prima mossa all'inizio del gioco e poi adotterai la stessa logica: appena il giocatore ha giocato, il computer fa la sua mossa.

L'idea che
Quote:
La grafica deve poter controllare ciclicamente lo stato della Partita
e vedere in che stato si trova.
E' decisamente sconsigliata, molto meglio adottare il pattern Observer, che, detto in estrema sintesi, funziona così: quando lo stato cambia, avvisa l'interfaccia grafica che quindi si aggiorna. In questo modo l'interfaccia non interroga continuamente lo stato ma lo fa solo quando è effettivamente necessario.
wingman87 è offline   Rispondi citando il messaggio o parte di esso
Old 22-01-2013, 23:39   #4
Groove89
Member
 
Iscritto dal: Jul 2006
Messaggi: 206
Forse non sono stato molto chiaro La logica funziona, il computer gioca, il giocatore gioca, riesco a svolgere una partita (tranne la fine che devo ancora gestire bene). Il mio problema primario è come far comunicare la grafica e la partita. L'interattività è la cosa che mi sta facendo uscire di testa
La grafica non può essere aggiornata da dentro la classe stessa quindi ho letto ieri dell'event dispatch thread e del worker thread che usati in modo opportuno permettono di gestire ciò che mi serve senza compromettere la grafica stessa. Questa strada andrebbe bene o il tuo consiglio di usare questo pattern observer (che ho già sentito accennare) è più di un consiglio?

Comunque devo riprecisare che la grafica prende un'istanza di partita. Ho il dubbio che si debba fare al contrario, ossia avviare la grafica
dalla classe partita, è così?
Sono riuscito ad aggiornare in modo poco carino la grafica quando gioca il giocatore perché quando deve giocare il giocatore la logica è ferma ed in attesa. Lo scegliere una carta equivale all'attivazione dell'actionListener relativo che sblocca la logica e aggiorna la grafica utilizzando proprio l'event dispatch thread. Il computer gioca in modo autonomo, per questo non posso fare la stessa identica cosa.

Ultima modifica di Groove89 : 22-01-2013 alle 23:45.
Groove89 è offline   Rispondi citando il messaggio o parte di esso
Old 23-01-2013, 09:31   #5
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
@Groove89: la tua soluzione al post #2 secondo me è valida in questo caso, perchè hai solo 6 stati da gestire. Se hai letto bene il vecchio post che citavi all'inizio (e soprattuto il tutorial su Swing di PGI-Bis che ho in firma) non avrai problemi.

Devi solo stare attento in quale thread fai cosa:
- mutazioni di componenti grafiche --> EDT (SwingUtilities.invokeLater o invokeAndWait a seconda dei casi per inserire delle istruzioni nella event queue).
- tutto il resto --> thread non EDT (il "main" thread più eventuali altri thread nuovi).

L'importante è che, leggendo e scrivendo il tuo codice, tu sappia dire senza incertezze quale metodo viene eseguito in quale thread.
__________________

As long as you are basically literate in programming, you should be able to express any logical relationship you understand.
If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it.
(Chris Crawford)
banryu79 è offline   Rispondi citando il messaggio o parte di esso
Old 23-01-2013, 10:15   #6
Groove89
Member
 
Iscritto dal: Jul 2006
Messaggi: 206
Stavo giusto approfondendo ora il pattern observer e devo dire che mi piace veramente tanto, il codice guadagnerebbe eleganza e andrei a disaccoppiare per bene grafica e logica Inoltre espanderò questo gioco in futuro aggiungendo una chat e il funzionamento in lan/rete quindi forse è meglio applicare fin da subito il pattern observer.

@banryu79
Penso che comunque devo andare ad utilizzare anche l'edt e cose varie unite al pattern observer giusto? Sono costretto. In particolare a me la classe GuiPartita estende JFrame ed implementa Observer, quindi avrà il metodo public void update(Observable obs, Object arg) che in base al tipo di notifica ricevuta dalla Partita (che implementa Observable) aggiorna la grafica. Per aggiornare la grafica devo usare l'edt. Sinceramente ho già provato ad aggiornare la grafica invocando invokeAndWait (creando un nuovo oggetto Runnable ecc.. ecc..) ma ho avuto una bella eccezione >.< Comunque, è questa la strada giusta almeno?

L'unica cosa che devo ancora capire bene è se la GuiPartita deve o non deve prendere la Partita nel costruttore e se è la Partita che deve avviare la GuiPartita.

Aggiornamento:

Sto lavorando da solo sempre in attesa di consigli ed ho cambiato un po l'impostazione visto che secondo me era corretta. La mia finestra principale (per avviare una nuova partita contro il pc oppure online) avvia la Gui a cui passa i Giocatori. La Gui a sua volta
avvia una partita a cui passa i Giocatori. Sembra funzionare. Per completezza riporto i pezzetti di codice interessanti:

Avvio dalla finestra principale
Codice:
...
record = new RecordClassifica(nome,0,0,0);
					classifica1.aggiungiRecord(record);
					//creo i giocatori
					Giocatore a = new Giocatore(nome);
					Giocatore b = new GiocatoreElettronico("Computer");
					//Avvio la partita
					GuiPartita gp = new GuiPartita("JBriscola 0.1",a,b,record);
					this.setVisible(false);
...
Avvio della partita (che estende observable) dalla gui (che implementa Observer):

Codice:
...
private Partita partita;

//Players and Record
	private Giocatore giocatore;
	private GiocatoreElettronico computer;
	private RecordClassifica record;

//costruttore
public GuiPartita(String titolo, Giocatore g, Giocatore c, RecordClassifica r) {

      super(titolo);
		
		this.giocatore = g;
		this.computer = (GiocatoreElettronico)c;
		this.record = r;
		
		partita = new Partita(giocatore,computer,record);
		partita.addObserver(this);
}

//Fuori dal costruttore..

	//Update Graphics Method
	public void update(Observable obs, Object obj) {
	
		MsgObserver msg = (MsgObserver)obj;
		//Da completare con tutti i thread relativi alle swing..
	}
Che ne dite? Questa discussione può essere utile a molti utenti! ^^

Ah ps, ho creato questa classe per i messaggi che la classe Partita può inviare alla grafica.

Codice:
package singleplayer;

public class MsgObserver {
	
	public final static int START = 0;        
	public final static int PC_GIOCATO = 1;
	public final static int TUTTI_GIOCATO = 2;
	public final static int USER_GIOCATO = 3;
	public final static int FINE = 4;
	
	public int code;
	public Object msg;
	
	public MsgObserver(int code, Object msg) {
		this.code = code;
		this.msg = msg;
	}
}

Ultima modifica di Groove89 : 23-01-2013 alle 13:53.
Groove89 è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


DJI Osmo Mobile 8: lo stabilizzatore per smartphone con tracking multiplo e asta telescopica DJI Osmo Mobile 8: lo stabilizzatore per smartph...
Recensione Pura 80 Pro: HUAWEI torna a stupire con foto spettacolari e ricarica superveloce Recensione Pura 80 Pro: HUAWEI torna a stupire c...
Opera Neon: il browser AI agentico di nuova generazione Opera Neon: il browser AI agentico di nuova gene...
Wind Tre 'accende' il 5G Standalone in Italia: si apre una nuova era basata sui servizi Wind Tre 'accende' il 5G Standalone in Italia: s...
OPPO Find X9 Pro: il camera phone con teleobiettivo da 200MP e batteria da 7500 mAh OPPO Find X9 Pro: il camera phone con teleobiett...
A 189,99€ con coupon: il NAS UGREEN che ...
Arm cresce ancora: ricavi oltre 1 miliar...
Xiaomi Redmi Note 14 5G ora a soli 179€:...
Spotify dovrà affrontare una nuov...
17,69€: praticamente regalato il caricat...
ECOVACS DEEBOT T80 OMNI, 600€ di sconto ...
EA fa chiarezza su controllo creativo e ...
Google Maps punta sull'AI: tante novit&a...
Qualcomm guarda oltre gli smartphone: ri...
539€, 629€ o 679€: 3 portatili HP o Acer...
Anche OnePlus attinge ai nomi scelti da ...
Apple non si arrende: altre due generazi...
Sky Mobile diventerà un vero e pr...
LG UltraGear OLED 27GX700A: debutta il p...
TIM e Poste lavorano a una joint venture...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 09:37.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Served by www3v