Torna indietro   Hardware Upgrade Forum > Software > Programmazione

DJI Lito 1 e Lito X1 recensione: i nuovi droni per principianti che non si fanno mancare nulla
DJI Lito 1 e Lito X1 recensione: i nuovi droni per principianti che non si fanno mancare nulla
DJI ha appena ufficializzato la serie Lito, la sua nuova gamma di droni entry-level destinata a chi si avvicina per la prima volta alla fotografia aerea. Al centro dell'annuncio ci sono due modelli ben distinti per fascia di prezzo e specifiche tecniche: DJI Lito 1 e DJI Lito X1. Entrambi si collocano sotto la soglia regolamentare dei 249 grammi, che permette di volare con requisiti burocratici più semplici rispetto ai droni più pesanti.
Sony World Photography Awards 2026: i premiati, anche italiani, il punto sulla fotografia di oggi
Sony World Photography Awards 2026: i premiati, anche italiani, il punto sulla fotografia di oggi
Siamo stati a Londra per la premiazione dei Sony World Photography Awards 2026, l'evento a tema fotografia più prestigioso. Fra sorprese e novità, ne approfittiamo per fare il punto sulla fotografia contemporanea, in cui la didascalia è sempre più necessaria a cogliere il senso della quasi totalità degli scatti.
Una settimana con Hyundai Ioniq 5 N-Line: diverte e convince
Una settimana con Hyundai Ioniq 5 N-Line: diverte e convince
L'elettrica di casa Hyundai propone una versione AWD con estetica derivata dalla famiglia N. L'abbiamo provata per diversi giorni, per scoprire tutti i dettagli e la vera autonomia in autostrada
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 03-11-2009, 01:16   #1
malocchio
Senior Member
 
L'Avatar di malocchio
 
Iscritto dal: Feb 2007
Città: Verona
Messaggi: 1060
[Java] Design degli eventi

Ho scritto a scopo didattico un'applicazione desktop per il tris, human vs. cpu .

Ho fatto un disegno classi che definisco decente, forse troppo elaborato, ma a scopo didattico.
In sintesi, così formata:

alcune enum
Codice:
public enum Player {
    HUMAN("X"),
    CPU("O"),
    NONE(" ");

    Player(String s) {
        this.s = s;
    }

    private String s;

    @Override
    public String toString() {
        return s;
    }
}
Codice:
public enum TrisState {
    HUMAN_WON("Human player won!"),
    CPU_WON("Cpu player won!"),
    DRAW("Draw!"),
    INCOMLETE("Your turn...");

    TrisState (String label) {
        this.label = label;
    }

    private String label;

    @Override
    public String toString() {
        return this.label;
    }
}
Un modello che rappresenta la griglia, che gestisce l'inserimento dei simboli, il controllo sui turni, l'update dell'interfaccia grafica, il controllo dei possibili risultati raggiunti (vinto, pari, continua...) e, guardacaso, la notifica tramite eventi di eventuali ascoltatori (su cui baserò le prossime classi da scrivere). In sintesi:
Codice:
public class TrisGridModel extends AbstractTableModel {

    private Player[][] grid;

    public TrisGridModel() {...}

    public TrisGridModel(Player[][] grid) {...}

    public int getRowCount() {...}

    public int getColumnCount() {...}

    public Player getValueAt(int r, int c) {...}

    @Override
    public void setValueAt(Object aValue, int r, int c) {...}

    public TrisState getState() {...}

    public boolean complete() {...}

    public Player tris() {...}

    private void switchNow() {...}

    //Ecco la gestione degli eventi

    private List<TrisGameListener> listeners;

    {
        this.listeners = new ArrayList<TrisGameListener>();
    }

    public void addTrisGameListener (TrisGameListener tgl) {...}

    public boolean removeTrisGameListener (TrisGameListener tgl) {...}
    
    private void fireTrisGameEvent (TrisGameEvent tge) {
        //TODO notifica dell'evento
        ...
    }
}
Questa è l'interfaccia TrisGameListener, che è scritta così ma potrà prevedere altri tipi di eventi.
Codice:
public interface TrisGameListener extends java.util.EventListener {

    public void movePerformed (TrisGameEvent tge);
    public void stateChanged (TrisGameEvent tge);
    
}
I miei dubbi:
vorrei progettare una gestione degli eventi in perfetto stile Swing, con eventi, ascoltatori e oggetti che generano eventi. Però non ho capito bene come si deve definire la classe che descrive un evento. Nel caso sopra (TrisGameListener) ci sono due possibili tipi di evento:
- un giocatore inserisce un simbolo (movePerformed(...))
- la griglia cambia di stato (vedi TrisGameState) (stateChanged(...))
Cosa devo scrivere nella classe TrisGameEvent? I metodi dell'ascoltatore che parametri devono prendere in ingresso?

L'interfaccia grafica comunica con la griglia (TrisGameModel) tramite gli eventi caratteristici della classe TableModel, infatti, nella classe della gui:
Codice:
public class TrisPanel extends JPanel {

    private JButton[][] grid;
    private TrisGridModel model;

    public TrisPanel () {...}

    public TrisPanel(TrisGridModel model) {
        this.model = model;
        this.model.addTableModelListener( new TrisModelListener() );
        ... 
    }

    public class TrisModelListener implements TableModelListener {

        public void tableChanged(TableModelEvent e) {...}

    }

}
Vorrei aggiungere anche la funzionalità "Hai vinto!" o "Hai perso!" o "Pari" proprio tramite eventi TrisGameEvent.

Altro dubbio: se ho un oggetto Swing con alcuni ascoltatori registrati ad esso, una volta che genera un evento e attiva i metodi degli ascoltatori, qual'è il thread in esecuzione? Posso agire su oggetti Swing direttamente oppure devo usare l'invokeLater() ??
__________________
malocchio è offline   Rispondi citando il messaggio o parte di esso
Old 03-11-2009, 10:28   #2
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
Quote:
I miei dubbi:
vorrei progettare una gestione degli eventi in perfetto stile Swing, con eventi, ascoltatori e oggetti che generano eventi. Però non ho capito bene come si deve definire la classe che descrive un evento. Nel caso sopra (TrisGameListener) ci sono due possibili tipi di evento:
- un giocatore inserisce un simbolo (movePerformed(...))
- la griglia cambia di stato (vedi TrisGameState) (stateChanged(...))
Cosa devo scrivere nella classe TrisGameEvent?
In TrisGameEvent ci metterai le cose che possono interessare a chi ascolta i due eventi.
Ad esmepio, il listener su cui viene invocato il metodo statChanged() sarà interessato a recuperare quello stato, per esaminarlo, percui il tuo TrisGameEvent potrebbe avere un membro di tipo TrisState e un metodo getter.

Nel caso di movePerformed() non so cosa possa interessare: se movePerformed rappresenta l'evento che accade quando un giocatore inserisce un simbolo potrebbe essere utile sapere quale istanza Palyer della griglia è cambiata e che valore ha.
Il valore lo si ricava dall'istanza Player stessa (codifica una String e ha ridefinito un toString() che la restituisce, e questa stringa rappresenta il suo valore).
L'istanza Player cambiata è identificata dalla sua posizione nella griglia, ovvero dai due indici che la identificano nell'array bidimensionale del TrisGridModel: perciò potrebbe essere utile, per l'ascoltatore, poter chiedere a TrisGameEvent la posizione dell'istanza Player cambiata.

Quote:
I metodi dell'ascoltatore che parametri devono prendere in ingresso?
Che io sappia i metodi che definiscono un listener in ingresso prendono solo un parametro: l'evento che ascoltano, cioè TrisGameEvent, nel tuo caso.


Quote:
Altro dubbio: se ho un oggetto Swing con alcuni ascoltatori registrati ad esso, una volta che genera un evento e attiva i metodi degli ascoltatori, qual'è il thread in esecuzione? Posso agire su oggetti Swing direttamente oppure devo usare l'invokeLater() ??
Se l'ascoltatore è stato registrato su una sorgente Swing, il thread che esegue il metodo invocato dell'ascoltatore è l'EDT.
Puoi vedere quale thread stia eseguendo un certo pezzo di codice chiamando Thread.currentThread() che torna una reference al thread corrente
__________________

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)

Ultima modifica di banryu79 : 03-11-2009 alle 11:30.
banryu79 è offline   Rispondi citando il messaggio o parte di esso
Old 08-11-2009, 15:55   #3
malocchio
Senior Member
 
L'Avatar di malocchio
 
Iscritto dal: Feb 2007
Città: Verona
Messaggi: 1060
Quote:
Originariamente inviato da banryu79 Guarda i messaggi
In TrisGameEvent ci metterai le cose che possono interessare a chi ascolta i due eventi.
Ad esmepio, il listener su cui viene invocato il metodo statChanged() sarà interessato a recuperare quello stato, per esaminarlo, percui il tuo TrisGameEvent potrebbe avere un membro di tipo TrisState e un metodo getter.

Nel caso di movePerformed() non so cosa possa interessare: se movePerformed rappresenta l'evento che accade quando un giocatore inserisce un simbolo potrebbe essere utile sapere quale istanza Palyer della griglia è cambiata e che valore ha.
Il valore lo si ricava dall'istanza Player stessa (codifica una String e ha ridefinito un toString() che la restituisce, e questa stringa rappresenta il suo valore).
L'istanza Player cambiata è identificata dalla sua posizione nella griglia, ovvero dai due indici che la identificano nell'array bidimensionale del TrisGridModel: perciò potrebbe essere utile, per l'ascoltatore, poter chiedere a TrisGameEvent la posizione dell'istanza Player cambiata.


Che io sappia i metodi che definiscono un listener in ingresso prendono solo un parametro: l'evento che ascoltano, cioè TrisGameEvent, nel tuo caso.



Se l'ascoltatore è stato registrato su una sorgente Swing, il thread che esegue il metodo invocato dell'ascoltatore è l'EDT.
Puoi vedere quale thread stia eseguendo un certo pezzo di codice chiamando Thread.currentThread() che torna una reference al thread corrente
Intanto grazie della risposta, chiara come sempre.
Scusami se non ho risposto subito, ho avuto da fare, ma il 3d rimane sempre aperto.

Ho inserito le modifiche nel codice sorgente e questo è quello che ho ottenuto:

Classe TrisGameEvent
Codice:
public class TrisGameEvent extends java.awt.AWTEvent {
    
    public static final int MOVE_PERFORMED = RESERVED_ID_MAX + 1;
    public static final int STATE_CHANGED = RESERVED_ID_MAX + 2;

    private int row;
    private int column;
    private Player player;
    private TrisState state;

    public TrisGameEvent(Object source, int type, int row, int column) {
        super(source, type);
        this.row = row;
        this.column = column;
    }

    public TrisGameEvent (Object source, int type, int row, int column, TrisState state) {
        this(source, type, row, column);
        this.state = state;
    }

    public TrisGameEvent(Object source, int type, int row, int column, Player player) {
        this(source, type, row, column);
        this.player = player;
    }

    public int getRow() {
        return row;
    }

    public int getColumn() {
        return column;
    }

    public TrisState getState() {
        return state;
    }

}
Classe TrisGridModel
Codice:
public class TrisGridModel extends AbstractTableModel {

    private Player[][] grid;
    private Player now;
    private TrisState prevState;

    public TrisGridModel() {...}

    public TrisGridModel(Player[][] grid) {...}

    public int getRowCount() {...}

    public int getColumnCount() {...}

    public Player getValueAt(int r, int c) {
        return this.grid[r][c];
    }

    public void setValueAt(Object aValue, int r, int c) {
        if (this.now == Player.NONE) return;
        if (r < this.getRowCount() && c < this.getColumnCount() && aValue instanceof Player) {
            if ( (Player)aValue == this.now ) {
                this.grid[r][c] = this.now;
                this.switchNow();
                this.fireMovePerformed(r, c, (Player) aValue);
            }
            
        } //FIXME else lancia una BRUTTA eccezione
    }

    public TrisState getState() {...}

    public boolean complete() {...}

    public Player tris() {...}

    private TrisGameListener listener;

    public void addTrisGameListener (TrisGameListener tgl) {
        listener = TrisGameEventMulticaster.add(listener, tgl);
    }

    public void removeTrisGameListener (TrisGameListener tgl) {
        listener = TrisGameEventMulticaster.remove(listener, tgl);
    }

    private void fireMovePerformed(int row, int column, Player player) {
        this.listener.movePerformed( new TrisGameEvent(this, TrisGameEvent.MOVE_PERFORMED, row, column, player) );
        this.fireTableCellUpdated(row, column);
        if (this.getState() != this.prevState) {
            this.prevState = this.getState();
            this.fireStateChanged(row, column, prevState);
        }
    }

    private void fireStateChanged(int row, int column, TrisState state) {
        this.listener.stateChanged( new TrisGameEvent(this, TrisGameEvent.STATE_CHANGED, row, column, state) );
    }
}
Ti sembra corretto?
__________________
malocchio è offline   Rispondi citando il messaggio o parte di esso
Old 09-11-2009, 08:49   #4
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
Beh, mi pare di sì.
A te la cosa funziona?
__________________

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 09-11-2009, 11:06   #5
malocchio
Senior Member
 
L'Avatar di malocchio
 
Iscritto dal: Feb 2007
Città: Verona
Messaggi: 1060
Quote:
Originariamente inviato da banryu79 Guarda i messaggi
Beh, mi pare di sì.
A te la cosa funziona?
Devo ancora utilizzarlo
Mi interessava la correttezza "logica"
__________________
malocchio è offline   Rispondi citando il messaggio o parte di esso
Old 09-11-2009, 11:45   #6
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
Quote:
Originariamente inviato da malocchio Guarda i messaggi
Devo ancora utilizzarlo
Mi interessava la correttezza "logica"
Bene, allora prendi tutto quello che ti ho scritto, che è il mio ragionamento in base alle mie conscenze (e ti avverto: sono molto lacunose in realtà, Swing lo sto ancora studiando e so poco) e leggile con occhio critico.

Se quello che cercavi era un cosiglio per implementare "in modo idiomatico" il tuo modello ad eventi allora non dare retta a quello che ti ho detto: ne so quanto te
__________________

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
 Rispondi


DJI Lito 1 e Lito X1 recensione: i nuovi droni per principianti che non si fanno mancare nulla DJI Lito 1 e Lito X1 recensione: i nuovi droni p...
Sony World Photography Awards 2026: i premiati, anche italiani, il punto sulla fotografia di oggi Sony World Photography Awards 2026: i premiati, ...
Una settimana con Hyundai Ioniq 5 N-Line: diverte e convince Una settimana con Hyundai Ioniq 5 N-Line: divert...
Recensione OPPO Find X9 Ultra: è lui il cameraphone definitivo Recensione OPPO Find X9 Ultra: è lui il c...
Ecovacs Deebot X12 OmniCyclone: lava grazie a FocusJet Ecovacs Deebot X12 OmniCyclone: lava grazie a Fo...
Il telescopio spaziale Nancy Grace Roman...
iPhone Ultra, periodo di lancio conferma...
Un anno fa debuttava Clair Obscur:&...
Tutte le offerte sugli smartphone ora pi...
Tutte le offerte sui TV ora su Amazon: u...
Xbox Game Pass sarà disponibile a...
La serie HONOR 600 avrà presto un...
Mova Viax 250 in prova: il robot tagliae...
Fat e-bike per tutti: sconti Engwe, pi&u...
Google conferma l'arrivo della nuova ver...
Apple ha trovato il modo per abbassare i...
OpenAI vuole tassare l'AI per dare a tut...
MacBook Air 15'' con chip M4 a 1.199€ su...
Samsung Galaxy S25 Edge 12/512GB a 854€ ...
Super offerta sul portatile gaming Acer ...
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: 18:35.


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