Visualizzazione dei risultati da 1 a 9 su 9
  1. #1

    Come comunicare tra più JFrame?

    Salve a tutti. Volevo chiedervi una cosa che può sembrare ovvia ma non lo è: come posso far comunicare più finestre in Java? Mi spiego meglio, mettiamo che abbia la prima finestra come questa:
    Screen.jpg
    (la parte centrale è una JTable)

    Quello che vorrei fare ora è che quando si preme il bottone "Aggiungi" compaia una schermata come la seguente:
    Nuova immagine bitmap.jpg

    Quindi quando si preme il pulsante "Conferma" viene restituito alla finestra principale l'oggetto creato con il secondo frame. Fino ad ora sono riuscito a far apparire i frame e a passargli tramite parametri dei puntatori allo stesso oggetto in modo che venga modificato. Però rimane il problema della sincronizzazione, ovvero, come fa la prima finestra a sapere quando la seconda ha terminato e quindi quando aggiornare la jTable?

  2. #2
    Utente di HTML.it
    Registrato dal
    Oct 2014
    residenza
    Padova
    Messaggi
    361
    Quote Originariamente inviata da mammolos Visualizza il messaggio
    Salve a tutti. Volevo chiedervi una cosa che può sembrare ovvia ma non lo è: come posso far comunicare più finestre in Java?
    Se ti basta ricevere un input dall'utente, puoi anche utilizzare i metodi statici della classe JOptionPane: ad esempio JOptionPane.showInputDialog(Component, Object) blocca l'applicazione e restituisce come valore di ritorno la stringa digitata dall'utente nella finestra che compare.

    Se vuoi far comunicare due finestre "custom", puoi benissimo passare a una finestra il reference dell'altra, nel tuo caso passi al costruttore della finestra anagrafica il reference del frame contenente la tabella e i pulsanti, lo memorizzi in una variabile, e potrai poi richiamare su questo reference il metodo per aggiornare la tabella, passando i dati che hai inserito in anagrafica.

    Quote Originariamente inviata da mammolos Visualizza il messaggio
    come fa la prima finestra a sapere quando la seconda ha terminato e quindi quando aggiornare la jTable?
    Questo dipende da cosa intendi per "ha terminato", la cosa più ovvia è richiamare il metodo una volta premuto il bottone "Confema", ma puoi scegliere tu: potresti voler aggiornare l'altro frame ad ogni carattere digitato nei campi codice e descrizione, o altro...

    Se scegli di aspettare il clic sul bottone, basta aggiungere un ascoltatore al pulsante (vedi ad esempio ActionListener), eventualemente controllare i dati inseriti, e poi passarli al tuo oggetto rappresentante il primo frame.
    Se hai dubbi su questa parte chiedi pure ma non è particolarmente complicato.

    Poi potresti decidere se lavorare con i due frame aperti in contemporanea, o aprire una finestra di dialogo quando vuoi aggiungere o modificare l'anagrafica.
    La prima soluzione è sconsigliata di solito, si sceglie più spesso di avere una sola finestra "focalizzabile", ad esempio con l'uso di un JDialog modale.

    Leggi ad esempio qui per maggiori chiarimenti (è una discussione spesso citata in altri forum...)

  3. #3
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da mammolos Visualizza il messaggio
    Quello che vorrei fare ora è che quando si preme il bottone "Aggiungi" compaia una schermata come la seguente:
    Nuova immagine bitmap.jpg
    Schermata che sarebbe meglio se fosse una dialog e soprattutto "modale", in modo che NON si possa interagire con la prima schermata finché la dialog non viene chiusa.

    Quote Originariamente inviata da mammolos Visualizza il messaggio
    Però rimane il problema della sincronizzazione, ovvero, come fa la prima finestra a sapere quando la seconda ha terminato e quindi quando aggiornare la jTable?
    Se fosse una dialog modale .....

    nel actionPerformed per il pulsante "Aggiungi" si potrebbe fare es.:

    codice:
    public void actionPerformed(ActionEvent e) {
        AnagraficaEditDialog dialog = new AnagraficaEditDialog(this);   // il this è riferito al frame corrente rispetto cui la dialog sarà "modale"
        Anagrafica nuovaAnagrafica = dialog.openDialog(null);    // null = non c'è una anagrafica in input ... questo è un "Aggiungi"
    
        // aggiungi nuovaAnagrafica nella tabella
    }

    Dove il costruttore di AnagraficaEditDialog andrà ad impostare la dialog e creare la GUI della dialog.
    E dove openDialog è un metodo nuovo (chiamalo come vuoi) che implementi tu e che a grandi linee farà:

    a) se il parametro Anagrafica non è null, assegna ai componenti i dati della anagrafica, in modo che ci sia una anagrafica iniziale già visibile (chiaramente quando è da editare)
    b) invoca setVisible(true) sulla dialog

    Se la dialog è "modale", il setVisible(true) è bloccante, ritorna solo quando la dialog viene chiusa. Nota: "bloccante" sì ma il ciclo degli eventi continua tranquillamente perché è interno alla gestione della dialog modale.

    Quando l'utente azionerà Conferma, farai in modo da eseguire semplicemente un dispose() sulla dialog. A quel punto il setVisible(true) che era bloccato all'interno del openDialog si sbloccherà e ritornerà. Nel openDialog farai ancora 2 step:

    c) dai componenti estrai i dati e costruisci un nuovo oggetto Anagrafica (tecnicamente se è un edit puoi anche modificare lo stato dell'Anagrafica ricevuta ma devi prestare più attenzione, non tanto su questo ma su dove userai l'oggetto solamente modificato).
    d) restituisce l'oggetto Anagrafica.

    Quindi di questo oggetto Anagrafica editato ne farai quello che vuoi ...


    Quello che hai chiesto lo puoi fare in svariati modi diversi, anche un po' "barbari". Quanto ti ho detto io è, se non il modo "migliore", perlomeno tra i modi migliori e puliti.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  4. #4
    Grazie ragazzi. Io vorrei farlo con più JFrame anche per una questione di esercitazione quindi l'opzione della dialog la salterei.
    Scusate la mia ignoranza, ma come si crea una finestra modale? Il valore di ritorno della seconda schermata (in questo caso Anagrafica) lo ritorno con una return nella funzione che richiamo esternamente che fa il setVisible(true)?

  5. #5
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da mammolos Visualizza il messaggio
    Io vorrei farlo con più JFrame anche per una questione di esercitazione quindi l'opzione della dialog la salterei.
    Male .... perché ti esponi a svariate problematiche/inconvenienti da valutare e risolvere.
    Se la finestra che permette di editare una anagrafica da aggiungere/modificare è un normale frame e non una dialog modale, allora la finestra dove c'è la tabella delle anagrafiche resta usabile e l'utente può interagirci indipendentemente dalla finestra di editazione.
    Vuoi forse che l'utente possa aprire più finestre di aggiunta/modifica? O no? In teoria dovresti disabilitare i controlli nella prima finestra quando l'utente vuole inserire/modificare una anagrafica.
    Se non lo fai, sorgono altri dubbi: che dovrebbe succedere se l'utente apre una anagrafica in modifica e poi sulla prima finestra cancella quella entry?
    Poi, dato che sono finestre di per sé indipendenti, cosa dovrebbe succedere se l'utente ha una finestra di aggiunta/modifica aperta e chiude la finestra della tabella?
    Insomma, ti stai tirando addosso un po' di grane.

    Quote Originariamente inviata da mammolos Visualizza il messaggio
    Scusate la mia ignoranza, ma come si crea una finestra modale?
    Il concetto di "modale" vale solo per le dialog. Vedi la documentazione javadoc di JDialog.

    Quote Originariamente inviata da mammolos Visualizza il messaggio
    Il valore di ritorno della seconda schermata (in questo caso Anagrafica) lo ritorno con una return nella funzione che richiamo esternamente che fa il setVisible(true)?
    Se fosse una dialog modale sì. Quello che ho detto vale SOLO nel caso di uso di una dialog modale. Se la finestra di editazione è un "frame" normale, NON puoi fare la logica che ho descritto per quel metodo specifico openDialog, perché il setVisible NON è bloccante sui frame.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  6. #6
    Ok, capito. Hai ragione che mi conviene usare le dialog però questo programmino per me serve solo a scopo didattico tanto per capire l'interazione tra frame anche perché potrebbero capitare casi un cui una dialog non sia sufficiente. Quindi come posso ritornare un oggetto inserito da una seconda finestra alla prima in modo che questa "aspetti" che l'altra abbia completato l'input? Si può? Se no, l'unico modo per fare tutto e passare i riferimenti degli oggetti su cui si vuole operare alla seconda finestra in modo che faccia tutto lei una volta premuto il pulsante di conferma?

  7. #7
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da mammolos Visualizza il messaggio
    però questo programmino per me serve solo a scopo didattico tanto per capire l'interazione tra frame anche perché potrebbero capitare casi un cui una dialog non sia sufficiente.
    Ok, va bene, se il senso e l'obiettivo è questo, non ho altre obiezioni.

    Quote Originariamente inviata da mammolos Visualizza il messaggio
    Quindi come posso ritornare un oggetto inserito da una seconda finestra alla prima in modo che questa "aspetti" che l'altra abbia completato l'input? Si può? Se no, l'unico modo per fare tutto e passare i riferimenti degli oggetti su cui si vuole operare alla seconda finestra in modo che faccia tutto lei una volta premuto il pulsante di conferma?
    Certo che si può e anche in svariati modi (dai più eleganti e "puliti" a quelli più "barbari").
    Ne dico giusto 2 davvero basilari (anche se non ottimali).

    Chiamerò il frame con la tabella AnagraficheFrame e quello per la editazione AnagraficaEditFrame. All'interno di AnagraficheFrame da qualche parte e in un certo momento andrai sicuramente ad istanziare un AnagraficaEditFrame. Il succo è che AnagraficheFrame HA quindi di certo il riferimento all'oggetto AnagraficaEditFrame. Questa è la base.

    Soluzione 1)
    Quando istanzi il AnagraficaEditFrame passi al suo costruttore il riferimento al AnagraficheFrame. Questo vuol anche dire che in questo caso AnagraficaEditFrame HA il riferimento al frame AnagraficheFrame.
    In AnagraficheFrame metti un metodo esposto all'esterno es. public void aggiungiAnagrafica(Anagrafica) (che come si può immaginare andrà ad inserire la anagrafica nella tabella).
    In AnagraficaEditFrame avrai di certo la gestione di un ActionListener per il "Conferma". Nel actionPerformed, prenderai i dati dai componenti, creerai un Anagrafica e invocherai quel aggiungiAnagrafica sul AnagraficheFrame (perché ripeto, HAI il riferimento).

    Soluzione 2)
    In AnagraficaEditFrame metti un metodo esposto all'esterno es. public void addConfermaActionListener(ActionListener). Esso farà semplicemente da passacarte e passerà il ActionListener al addActionListener del JButton "Conferma".
    Sempre in AnagraficaEditFrame metti un metodo esposto all'esterno es. public Anagrafica getAnagrafica() che prende i dati dai componenti, crea un Anagrafica e lo restituisce.
    Poi in AnagraficheFrame implementi un ActionListener (come/dove non è molto importante) e lo passi al addConfermaActionListener invocato chiaramente sulla istanza di AnagraficaEditFrame.
    Qui il succo è che quando "Conferma" viene azionato, il listener notificato è in AnagraficheFrame invece che in AnagraficaEditFrame. Il suo actionPerformed semplicemente invocherà getAnagrafica sul AnagraficaEditFrame e siamo allo stesso punto della soluzione 1, cioè in AnagraficheFrame hai un oggetto Anagrafica da inserire nella tabella.


    Come vedi sono due soluzioni differenti ma con lo stesso obiettivo e risultato. Cambia solo CHI fa COSA rispetto a CHI. Queste due soluzioni non sono nulla di che ... e nemmeno davvero buone e ottimali. Sono semplicemente l'uso basilare di oggetti e riferimenti. Perché se noti è sempre un metodo (almeno uno) X invocato su un oggetto Y. Su questo non si scappa.

    Cambiano invece le relazioni tra le due classi. Nel primo caso le due classi sono strettamente legate tra di loro, perché AnagraficaEditFrame SA di AnagraficheFrame e ci invoca un metodo specifico. Questo in generale non è buono.
    Nel secondo caso AnagraficaEditFrame riceve da AnagraficheFrame soltanto un ActionListener (è una interfaccia), che può essere implementato in maniera differenza ma è tutto lì, non sa altro di specifico.

    Se tu volessi (ri)usare AnagraficaEditFrame anche da un'altra classe es. RevisioneAnagraficheFrame, con la soluzione 2 puoi riutilizzare AnagraficaEditFrame anche in questa perché non c'è un legame così stretto. La soluzione 1 non andrebbe bene se avevi già legato AnagraficaEditFrame direttamente a AnagraficheFrame.

    Ultima cosa: quello che NON dovrai mai fare è "esporre" o passare componenti grafici tra le due classi. Questo è proprio lo scenario da evitare come la peste.


    Se tutto questo ti risulta chiaro, allora come si dice "sei a cavallo" e puoi sicuramente andare anche oltre. Se non ti è chiaro, rileggi il tutto e magari poni domande.
    Ultima modifica di andbin; 10-10-2016 a 21:18
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  8. #8
    Quote Originariamente inviata da andbin Visualizza il messaggio
    Ok, va bene, se il senso e l'obiettivo è questo, non ho altre obiezioni.
    Soluzione 2)
    In AnagraficaEditFrame metti un metodo esposto all'esterno es. public void addConfermaActionListener(ActionListener). Esso farà semplicemente da passacarte e passerà il ActionListener al addActionListener del JButton "Conferma".
    Sempre in AnagraficaEditFrame metti un metodo esposto all'esterno es. public Anagrafica getAnagrafica() che prende i dati dai componenti, crea un Anagrafica e lo restituisce.
    Poi in AnagraficheFrame implementi un ActionListener (come/dove non è molto importante) e lo passi al addConfermaActionListener invocato chiaramente sulla istanza di AnagraficaEditFrame.
    Qui il succo è che quando "Conferma" viene azionato, il listener notificato è in AnagraficheFrame invece che in AnagraficaEditFrame. Il suo actionPerformed semplicemente invocherà getAnagrafica sul AnagraficaEditFrame e siamo allo stesso punto della soluzione 1, cioè in AnagraficheFrame hai un oggetto Anagrafica da inserire nella tabella.
    La prima soluzione sono riuscito a comprenderla perfettamente e rimpiango il fatto che non ci abbia pensato prima ahahah
    La seconda soluzione invece non l'ho capita molto, anche perché non sono molto pratico degli ActionListener. Da quello che ho capito il gestore dell'evento generato quando si preme il pulsante di conferma in AnagraficaEditFrame viene passato ad AnagraficheFrame il quale, al verificarsi dell'evento, richiamerà un metodo che restituisce un oggetto basandosi sui dati inputati nella finestra AnagraficaEditFrame. In modo pratico, come si fa a passare l'ActionListener, puoi farmi un piccolissimo esempio? Inoltre, dopo aver passato l'ActionListener ad AnagraficheFrame, questo potrà comunque continuare ad essere utilizzato nella finestra originale, AnagraficaEditFrame?

  9. #9
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da mammolos Visualizza il messaggio
    anche perché non sono molto pratico degli ActionListener.
    Allora hai bisogno di più "basi" su Swing. Non puoi farne a meno (visti, tra l'altro, gli obiettivi che ti stai prefiggendo).

    Quote Originariamente inviata da mammolos Visualizza il messaggio
    Da quello che ho capito il gestore dell'evento generato quando si preme il pulsante di conferma in AnagraficaEditFrame viene passato ad AnagraficheFrame il quale, al verificarsi dell'evento, richiamerà un metodo che restituisce un oggetto basandosi sui dati inputati nella finestra AnagraficaEditFrame. In modo pratico, come si fa a passare l'ActionListener, puoi farmi un piccolissimo esempio? Inoltre, dopo aver passato l'ActionListener ad AnagraficheFrame, questo potrà comunque continuare ad essere utilizzato nella finestra originale, AnagraficaEditFrame?
    codice:
    public class AnagraficaEditFrame extends JFrame {
        // .....altri componenti.....
        private JButton confermaButton;
    
    
        public void addConfermaActionListener(ActionListener al) {
            confermaButton.addActionListener(al);
        }
    
        public Anagrafica getAnagrafica() {
            return ....... // Dai valori dei componenti crei un Anagrafica che restituisci
        }
    
        // ......
    }

    codice:
    public class AnagraficheFrame extends JFrame {
    
    
            // da qualche parte in AnagraficheFrame
            AnagraficaEditFrame editFrame = new AnagraficaEditFrame();
    
            editFrame.addConfermaActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    Anagrafica anag = editFrame.getAnagrafica();
                    // .... usa anag
                }
            });
    
            editFrame.setVisible(true);
    
    
    }

    L'ActionListener l'ho implementato come anonymous inner class. Ma si può fare diversamente. Dove/come è implementato il listener NON è importante per AnagraficaEditFrame, in quanto al JButton interessa solo avere un oggetto di una classe che è-un ActionListener.


    Nota: se sei < Java 8 e quel editFrame è una variabile "locale", va messa final
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.