SWING - Utilizzo dei listener tra oggetti

di il
6 risposte

SWING - Utilizzo dei listener tra oggetti

Ciao,
sto implementando un "programmino" con il quale dovrò permettere all'utente di selezionare alcuni campi da un'interfaccia grafica.

In pratica ho un oggetto "Ricezione" che contiene una lista di oggetti "Tabella" che a sua volta contiene una lista di oggetti "Campo". Ho implementato un'interfaccia che contiene 3 liste rispettivamente agli oggetti sopra citati.

La lista 1 contiene l'elenco delle ricezioni che valorizzo inizialmente poi le altre due liste devono essere popolate interattivamente, la lista delle tabelle deve essere popolata in base a quale ricezione viene selezionata e la lista dei campi in base a quale tabella viene selezionata.

Ho già realizzato qualcosa realizzando l'intera interfaccia in un'unica classe "Finsetra" utilizzando i listener per il riempimento interattivo delle liste "Tabella" e "Campo". Il tutto funziona bene, anche se è solo una bozza e dovrò aggiungere dei controlli, ma è poco ordinato il codice, avevo pensato quindi di creare una classe per ogni component, nel mio caso:
  • 1. Classe "ListaRicezioni"
    2. Classe "ListaTabelle"
    3. Classe "Lista campi"
tutte e tre che estendo la classe JList.

A questo punto dovrei aggiungere un listener "mouseClicked" nella classe "ListaRicezione" che dovrebbe popolare gli elementi della classe "ListaTabelle" ma non saprei come fare.

Spero di essere stato chiaro.

Grazie in anticipo, ciao.

Michele

6 Risposte

  • Re: SWING - Utilizzo dei listener tra oggetti

    charlesmm ha scritto:


    avevo pensato quindi di creare una classe per ogni component, nel mio caso:
    • 1. Classe "ListaRicezioni"
      2. Classe "ListaTabelle"
      3. Classe "Lista campi"
    tutte e tre che estendo la classe JList.
    Uhm ... no mi sembra molto "dubbio" così. JList raramente lo si estende.

    Se ho ben capito, le tre liste sono gestite in "cascata", nel senso che una scelta sulla prima va a cambiare totalmente la lista nella seconda. E una scelta sulla seconda va a cambiare totalmente la lista nella terza. Giusto?
    Queste cose sono assolutamente fattibili. Ma non estendendo JList. Si dovrebbe ragionare meglio a livello di "modello" dei dati.

    charlesmm ha scritto:


    A questo punto dovrei aggiungere un listener "mouseClicked" nella classe "ListaRicezione" che dovrebbe popolare gli elementi della classe "ListaTabelle" ma non saprei come fare.
    MouseListener va bene solo se devi fare cose particolari a "basso" livello con il mouse ma se vuoi solo ascoltare il cambio di "selezione" nella lista, allora vedi il addListSelectionListener(ListSelectionListener listener) .
  • Re: SWING - Utilizzo dei listener tra oggetti

    Ciao Andrea,
    intanto grazie per la risposta precedente e scusami per la mancata risposta da parte mia ma sono stato un po' "assente"

    Riprendo questo topic in quanto mi ritrovo ad affrontare lo stesso problema per una nuova esercitazione. Nel dettaglio, sto implementando il "Gioco del 15". L'obbiettivo è quello di avere un JFrame che contenga una JMenuBar (con i menù "Nuova partita" e "Esci") e un JPanel che contenga i 15 bottoni più la cella vuota.

    Avevo intenzione di dividere i component in classi diverse:
    • classe 'Quindici' che estende JFrame
    • classe 'MyMenuBar' che estende JMenuBar
    All'oggetto "Quindici" aggiungerò l'oggetto JMenuBar e il JPanel (inizialmente contenente i 15 bottoni ordinati da 1 a 15) e vorrei che l'azione del tasto
    "Nuova partita" mischi i bottoni del JPanel, come potrei fare?

    Grazie in anticipo, ciao.

    Michele
  • Re: SWING - Utilizzo dei listener tra oggetti

    charlesmm ha scritto:


    Avevo intenzione di dividere i component in classi diverse:
    • classe 'Quindici' che estende JFrame
    • classe 'MyMenuBar' che estende JMenuBar
    All'oggetto "Quindici" aggiungerò l'oggetto JMenuBar e il JPanel (inizialmente contenente i 15 bottoni ordinati da 1 a 15) e vorrei che l'azione del tasto
    "Nuova partita" mischi i bottoni del JPanel, come potrei fare?
    Io, personalmente, non estenderei JMenuBar ma non è comunque impossibile o totalmente errato. Se estendi JMenuBar, nella MyMenuBar andrai per forza a popolare il menù bar creando e innestando i vari JMenu e JMenuItem.

    La vera questione è un'altra. DOVE pensi di implementare il/i listener per i vari menù item? Perché da questo dipende come andrai a "legare" le varie classi.
  • Re: SWING - Utilizzo dei listener tra oggetti

    A mio parere le tue classi 'Quindici' e 'MyMenuBar' non sono al momento la parte "importante" del programma, dovresti concentrarti più sulla logica del gioco e dell'interazione che avrà l'utente con il pannello dove si svolgerà il gioco.
    Questo a meno che tu non volessi sviluppare tutta la logica del gioco nella classe del JFrame, ma io ti consiglierei di spezzarlo in più parti:

    - Una classe che funga da "modello", che memorizzi cioè la situazione corrente del campo di gioco (es. in una matrice), e abbia metodi per controllare che il gioco sia vinto, mischiare i numeri casualmente all'inizio della partita, fare l'aggiornamento dopo ogni mossa etc.
    - Una classe che funga da "vista", che inglobi un'istanza della classe modello, e vada ad interagire con essa: ai pulsanti andresti quindi a settare ogni volta il testo in base al numero che in quel momento è presente sul campo di gioco, e alla pressione di un pulsante andresti ad aggiornare il modello.

    Poi avrai ovviamente i listener.

    Non è ovviamente l'unico modo, potresti anche associare ogni pulsante a un numero e spostare direttamente il pulsante, mantenendo fisso il numero, ma io eviterei questo approccio, la parte logica del programma non è bene incapsulata e sei più esposto ad errori e problemi.

    In ogni caso se usi dei pulsanti ci dovrà essere un qualche spostamento, perché se non sbaglio lo spazio vuoto della griglia cambia durante il gioco, io comunque lo limiterei il più possibile...
    Che tipo di layout pensavi di adottare per sistemare i bottoni nella griglia? Un GridLayout? Un GridBagLayout? Altro?
    Diciamo che con un GridLayout lo spazio vuoto sarebbe un po' un problema, di solito si aggiunge un componente vuoto alla griglia, ma poi per fare gli spostamenti penso che tu sia costretto a togliere i componenti e reinserirli nel giusto ordine, mentre con un GridBagLayout dovrebbe essere possibile agire sulle coordinate dei compoenenti e semplificare un po' questa parte, con altri layout adesso non saprei (ma non usare il posizionamento assoluto!).

    Potresti anche optare per una diversa soluzione (che è quella implementata ad esempio in questo programmino che ho trovato online): non usi pulsanti o altri componenti, ma disegni tu la griglia nel pannello facendo l'override del paintComponent per il tuo pannello e utilizzando i metodi della classe Graphics.

    Secondo me queste scelte dovrebbero determinare il modo in cui imposterai poi le altre classi, come dice @andbin estendere JMenuBar potresti anche evitarlo, aggiungo io che c'è anche una corrente di pensiero (predominante nel link che sto per fornirti) che suggerisce di non estendere JFrame.
    Questo per più motivi, ma in particolare perché un JPanel è più flessibile, e se fai una classe es. GamePanel che contiene tutta la logica dell'interfaccia poi puoi aggiungerla a un JFrame, JDialog, JApplet, o inserirlo dentro un altro pannello (ad esempio in un CardLayout per scambiare i pannelli come potresti fare tra un menù e il pannello di gioco etc.).
    Se ti interessa il link della discussione è questo: https://stackoverflow.com/questions/22003802/extends-jframe-vs-creating-it-inside-the-program , poi non voglio assolutamente dire che una delle due soluzioni "sia sbagliata" (personalmente ho usato entrambi gli approcci più volte), era solo per dirti di pensare prima al cuore del programma, che poi il resto è "di contorno".

    Per concludere in generale il fatto di "mischiare" i numeri lo puoi ottenere facilmente con metodi già implementati come Collections.shuffle (), è da vedere però a che livello vuoi agire, se mischiare direttamente i pulsanti o mischiare i numeri in una matrice o in una qualche altra struttura dati per poi modificare la tua interfaccia di conseguenza (io appunto farei in questo modo).

    Per qualsiasi cosa siamo qui
  • Re: SWING - Utilizzo dei listener tra oggetti

    Ciao,
    intanto grazie ad entrambi.

    Ansharja ha scritto:


    A mio parere le tue classi 'Quindici' e 'MyMenuBar' non sono al momento la parte "importante" del programma, dovresti concentrarti più sulla logica del gioco e dell'interazione che avrà l'utente con il pannello dove si svolgerà il gioco.
    Ho già implementato qualcosa sia della finestra sia della logica. Ho fatto in modo che quando viene instanziato un nuovo oggetto di "Quindici" venga visualizzata una finestra con la manuBar contenente gli itemMenu "Nuova partita" e "Esci" e un JPanel contenente i 15 bottoni ordinati da 1 a 15 con in più il bottone disattivato (che rappresenterà la cella vuota).

    Ho già implementato i seguenti metodi:
    * iniziaPartita, che serve a mischiare l'ordine dei bottoni e che vorrei associare al click sul itemMenu "Nuova partita".
    * controllaVittoria, che confronta appunto lo stato della griglia con la griglia di vittoria (le griglie le ho rappresentate con un ArrayList di Integer)

    Sono presenti poi un'altra serie di proprità come il numero delle mosse, l'indice della cella vuota, ecc...

    a questo punto mi sono posto il problema di come fare e mi aggancio a quanto indicato da andbin

    andbin ha scritto:


    La vera questione è un'altra. DOVE pensi di implementare il/i listener per i vari menù item? Perché da questo dipende come andrai a "legare" le varie classi.
    Il mio problema è proprio questo.. non ne ho idea
    Siccome mi ritrovo con gli itemMenu presenti nella classe MyMenuBar, come faccio ad implementare un listener che riesca ad "interagire" con il JPanel, che invece si trova nella classe "Quindici", per poter mischiare i bottoni?

    Spero di aver saputo esprire la mia difficoltà.

    Grazie ancora, ciao.

    Michele
  • Re: SWING - Utilizzo dei listener tra oggetti

    Io fossi in te non userei proprio la classe MyMenuBar, come suggerisce anche @andbin.

    Terrei invece una classe per il tuo pannello di gioco, QuindiciGamePanel o come vuoi chiamarla, che abbia all'interno tutte le informazioni relative all'interazione con l'utente e alla logica del gioco (che secondo me, come dicevo, dovrebbero a loro volte essere inserite in una classe che funga da modello).

    Da qualche parte dovrai pur aggiungere quel tuo pannello di gioco al frame, che sia in una classe che estende JFrame o in un metodo (di solito statico) che viene richiamato direttamente dal main e crea l'interfaccia. Nel momento in cui aggiungi il pannello al frame ne hai il reference, e puoi quindi creare i listener che poi passerai alla menu bar.

    Ad esempio, in modo molto abbozzato, se vuoi una classe che estenda JFrame potresti fare qualcosa del genere:
    
    public class QuindiciFrame extends JFrame
    {
    	public QuindiciFrame () {
    		// ... crei il frame e ne setti le proprietà ...
    		
    		QuindiciGamePanel gamePanel = new QuindiciGamePanel (); // contiene tutta la logica dell'interazione con l'utente al suo interno ...
    		
    		// Crei i listener per la menu bar, oppure (cosa che farei io) crei direttamente qui la menubar senza avere un'altra classe ...
    		JMenuBar menuBar = ...;
    		JMenuItem newGameMenuItem = new JMenuItem (new AbstractAction ("New Game") {
    			@Override public void actionPerformed (ActionEvent e) {
    				gamePanel.startNewGame (); // il tuo metodo per iniziare una nuova partita ...
    			}
    		});
    		JMenuItem ...
    		
    		menuBar.add (...);
    		
    		// Aggiungi al frame il pannello di gioco e setti la menu bar ...
    		
    		this.setContentPane (gamePanel);
    		this.setJMenuBar (menuBar);
    		
    		// ... chiudi il frame, setti la location, etc ...
    	}
    }
    
    In questo modo hai tutto lì, non serve ad esempio passare il reference del pannello di gioco alla classe che estende JMenuBar per poterci richiamare sopra i metodi che ti servono, cosa che darebbe alla MyMenuBar delle potenzialità/compiti che non dovrebbe avere (che io sappia in genere si cerca di limitare il passaggio di componenti tra le varie classi).

    Io personalmente farei qualcosa del genere, probabilmente ad altri verranno in mente soluzioni più eleganti.
Devi accedere o registrarti per scrivere nel forum
6 risposte