L'uso di più JFrame: buona o cattiva pratica? [chiuso]


531

Sto sviluppando un'applicazione che visualizza immagini e riproduce suoni da un database. Sto cercando di decidere se utilizzare o meno un JFrame separato per aggiungere immagini al database dalla GUI.

Mi chiedo solo se è buona norma utilizzare più finestre JFrame?


11
Solo se stai prendendo di mira una configurazione multi-monitor!
DNA,

17
Direi anche che questo è indipendente dal linguaggio e ha a che fare con l' interfaccia utente più di Java in particolare.
wchargin,

6
Sono d'accordo con questo @WChargin Questa domanda è diventata più preziosa di quanto avessi mai pensato!
Venditore ambulante

1
Ho notato che i principianti (come me) di solito fanno uso di più JFrame. Probabilmente perché è più facile chiamarlo dall'interno del JFrame piuttosto che usare un CardLayout. Anche se in alcuni casi non è consigliabile utilizzarlo.
Hoodlum,

Il debug sarebbe come mangiare cactus ... questo non è consigliabile.
Taslim Oseni,

Risposte:


447

Mi chiedo solo se è una buona pratica usare più JFrame?

Pratica cattiva (cattiva, cattiva).

  • Utente ostile: l'utente vede più icone nella barra delle attività quando si aspetta di vederne solo una. Inoltre gli effetti collaterali dei problemi di codifica.
  • Un incubo per codificare e mantenere:
    • Una finestra di dialogo modale offre la semplice opportunità di focalizzare l'attenzione sul contenuto di quella finestra di dialogo: scegli / correggi / annulla, quindi procedi. I frame multipli no.
    • Una finestra di dialogo (o barra degli strumenti mobile) con un genitore apparirà in primo piano quando si fa clic sul genitore - dovresti implementarlo in frame se quello fosse il comportamento desiderato.

Esistono diversi modi per visualizzare molti elementi in una GUI, ad esempio:

  • CardLayout(breve demo. ). Buono per:
    1. Mostra procedura guidata come dialoghi.
    2. Visualizzazione delle selezioni di elenchi, alberi, ecc. Per gli elementi a cui è associato un componente.
    3. Sfogliando tra nessun componente e componente visibile.
  • JInternalFrame/JDesktopPane tipicamente utilizzato per un MDI .
  • JTabbedPane per gruppi di componenti.
  • JSplitPane Un modo per visualizzare due componenti di cui l'importanza tra l'una o l'altra (la dimensione) varia in base a ciò che l'utente sta facendo.
  • JLayeredPane molti componenti ben ... sovrapposti.
  • JToolBarin genere contiene gruppi di azioni o controlli. Può essere trascinato nella GUI o disattivato completamente in base alle esigenze dell'utente. Come accennato in precedenza, minimizzerà / ripristinerà in base al genitore che lo fa.
  • Come elementi in un JList(semplice esempio di seguito).
  • Come nodi in a JTree.
  • Layout nidificati .

Ma se tali strategie non funzionano per un particolare caso d'uso, provare quanto segue. Stabilire un singolo principale JFrame, quindi visualizzare JDialogo JOptionPaneistanze per il resto degli elementi fluttuanti, usando il frame come genitore per le finestre di dialogo.

Molte immagini

In questo caso in cui gli elementi multipli sono immagini, sarebbe preferibile utilizzare una delle seguenti opzioni:

  1. Un singolo JLabel(centrato in un riquadro di scorrimento) per visualizzare l'immagine a cui l'utente è interessato in quel momento. Come visto in ImageViewer.
  2. Una singola fila JList. Come visto in questa risposta . La parte "riga singola" funziona solo se hanno tutte le stesse dimensioni. In alternativa, se si è pronti a ridimensionare le immagini al volo e hanno tutte le stesse proporzioni (ad es. 4: 3 o 16: 9).


4
@AndrewThompson Non mi ero mai imbattuto in una situazione in cui avevo bisogno di più JFrames prima e non avevo mai considerato quei problemi, grazie per avermi spiegato!
Jeffrey,

4
@ user417896 "Dipende solo." No non lo fa. Ho usato Gimp. È orribile e dovrebbe essere un MDI.
Andrew Thompson,

4
@ryvantage "Dovrebbe (Excel) essere MDI?" Buona domanda. Penso che dovrebbe essere offerto all'utente in entrambi i modi (certamente non solo in forma MDI). Ad esempio: 1) Attualmente utilizzo TextPad e, a mia scelta, apre istanze separate che offrono più documenti mostrati in un elenco. 2) Anche se in genere utilizzo FF in modalità a schede, di tanto in tanto trascino una scheda in una nuova finestra. - Il fattore comune negli esempi è la scelta dell'utente. Consegna l'app. 'comunque l'utente lo desidera'.
Andrew Thompson,

12
@AndrewThompson Hai appena contrastato il tuo argomento con il tuo ultimo commento. Nella tua risposta principale dici che questa è una cattiva pratica e non dovrebbe mai essere fatta, ma nel tuo commento sopra dici che a volte ti piace SDI e dovremmo offrire ai nostri utenti la scelta. Sicuramente, questo è esattamente ciò che user417896 stava dicendo sopra. Dipende. Questo è uno dei miei più grandi odia per i miei compagni sviluppatori. Il fatto che molti di loro diventino religiosamente fanatici delle cosiddette "migliori pratiche". Non avremmo le interfacce utente innovative che abbiamo oggi se ci attenessimo tutti alle "migliori pratiche" e non pensassimo al di fuori del quadrato.
DuncanKinn, il

4
Grande generalizzazione! Non è sempre male consentire all'utente di controllare le proprie finestre individualmente e accedervi individualmente dalla barra delle attività. La buona pratica è essere consapevoli di tutte le opzioni e sceglierne una in modo intelligente. Ci sono certamente casi in cui più JFrames hanno un buon senso.
Dawood ibn Kareem,

203

L' JFrameapproccio multiplo è stato implementato da quando ho iniziato a programmare app Swing. Per la maggior parte, l'ho fatto all'inizio perché non sapevo niente di meglio. Tuttavia , mentre maturavo nella mia esperienza e conoscenza come sviluppatore e mentre iniziavo a leggere e assorbire le opinioni di tanti altri sviluppatori Java con esperienza online, ho fatto un tentativo di abbandonare l' JFrameapproccio multiplo (sia nei progetti attuali che in quelli futuri ) solo per incontrare ... ottenere questa ... resistenza dai miei clienti! Quando ho iniziato a implementare finestre di dialogo modali per controllare finestre "secondarie" JInternalFrameper componenti separati, i miei clienti hanno iniziato a lamentarsi!Sono stato piuttosto sorpreso, mentre stavo facendo quello che pensavo fosse la migliore pratica! Ma, come si suol dire, "Una moglie felice è una vita felice". Lo stesso vale per i tuoi clienti. Certo, sono un appaltatore, quindi i miei utenti finali hanno accesso diretto a me, lo sviluppatore, che ovviamente non è uno scenario comune.

Quindi, spiegherò i vantaggi dell'approccio multiplo JFrame, oltre a rompere il mito alcuni dei contro che altri hanno presentato.

  1. Massima flessibilità nel layout - Consentendo i messaggi separati JFrame, offri al tuo utente finale la possibilità di diffondere e controllare ciò che è sul suo schermo. Il concetto sembra "aperto" e non costrittivo. Lo perdi quando vai verso un grande JFramee un mucchio di JInternalFrames.
  2. Funziona bene per applicazioni molto modulari - Nel mio caso, la maggior parte delle mie applicazioni ha 3-5 grandi "moduli" che non hanno davvero nulla a che fare l'uno con l'altro. Ad esempio, un modulo potrebbe essere un dashboard di vendita e uno potrebbe essere un dashboard di contabilità. Non parlano tra di loro o altro. Tuttavia, l'esecutivo potrebbe voler aprire entrambi e questi essendo frame separati sulla barra delle applicazioni rende la sua vita più semplice.
  3. Semplifica la consultazione da parte degli utenti finali di materiale esterno : una volta ho avuto questa situazione: la mia app aveva un "visualizzatore di dati", da cui era possibile fare clic su "Aggiungi nuovo" e si apriva una schermata di immissione dei dati. Inizialmente, entrambi erano JFrames. Tuttavia, volevo che la schermata di immissione dei dati fosse un JDialogcui genitore era il visualizzatore di dati. Ho apportato la modifica e ho ricevuto immediatamente una chiamata da un utente finale che si basava fortemente sul fatto che poteva ridurre al minimo o chiudere lo spettatore e tenere aperto l' editor mentre faceva riferimento a un'altra parte del programma (o a un sito Web, don non ricordo). E ' non è su un multi-monitor, in modo che gli serviva la finestra di ingresso di essere il primo e qualcos'altroin secondo luogo, con il visualizzatore di dati completamente nascosto. Questo era impossibile con un JDialoge certamente sarebbe stato impossibile anche con un JInternalFrame. A malincuore l'ho cambiato di nuovo in separato JFramesper la sua sanità mentale, ma mi ha insegnato una lezione importante.
  4. Mito: difficile da codificare - Questo non è vero nella mia esperienza. Non vedo perché sarebbe più facile creare un JInternalFrameche un JFrame. In effetti, nella mia esperienza, JInternalFramesoffro molta meno flessibilità. Ho sviluppato un modo sistematico di gestire l'apertura e la chiusura di JFrames nelle mie app che funziona davvero bene. Controllo il frame quasi completamente dall'interno del codice del frame stesso; la creazione di nuovi frame SwingWorkerche controllano il recupero di dati su thread in background e il codice GUI su EDT, ripristinando / portando in primo piano il frame se l'utente tenta di aprirlo due volte, ecc. Tutto ciò che serve per aprire il mio JFrameè chiama un metodo statico pubblico open()e il metodo aperto, combinati con unwindowClosing() L'evento gestisce il resto (il frame è già aperto? Non è aperto, ma in fase di caricamento? ecc.) Ho trasformato questo approccio in un modello, quindi non è difficile implementarlo per ogni frame.
  5. Mito / Non provato: Risorsa pesante - Mi piacerebbe vedere alcuni fatti dietro questa affermazione speculativa. Sebbene, forse, potresti dire che ha JFramebisogno di più spazio di un JInternalFrame, anche se apri 100 JFrames, quante più risorse consumeresti davvero? Se la vostra preoccupazione è la perdita di memoria a causa delle risorse: la chiamata dispose()libera tutte le risorse utilizzate dal frame per la garbage collection (e, ripeto, JInternalFramedovrei invocare esattamente la stessa preoccupazione).

Ho scritto molto e mi sento di poter scrivere di più. Comunque, spero di non essere votato verso il basso semplicemente perché è un'opinione impopolare. La domanda è chiaramente preziosa e spero di aver fornito una risposta preziosa, anche se non è l'opinione comune.

Un ottimo esempio di più frame / singolo documento per frame ( SDI ) vs singolo frame / più documenti per frame ( MDI ) è Microsoft Excel. Alcuni dei vantaggi dell'MDI:

  • è possibile avere alcune finestre di forma non rettangolare, in modo che non nascondano il desktop o altre finestre da un altro processo (ad es. browser web)
  • è possibile aprire una finestra da un altro processo su una finestra di Excel mentre si scrive nella seconda finestra di Excel - con MDI, il tentativo di scrivere in una delle finestre interne darà fuoco all'intera finestra di Excel, nascondendo quindi la finestra da un altro processo
  • è possibile avere documenti diversi su schermi diversi, il che è particolarmente utile quando gli schermi non hanno la stessa risoluzione

SDI (Single-Document Interface, ovvero ogni finestra può avere un solo documento):

inserisci qui la descrizione dell'immagine

MDI (Multiple-Document Interface, ovvero ogni finestra può avere più documenti):

inserisci qui la descrizione dell'immagine


16
Ben pensato. Se hai più moduli che non hanno nulla a che fare l'uno con l'altro, perché non creare applicazioni separate? Inoltre, non ci sono restrizioni che dicono che devi usare dialoghi modali , potresti usare dialoghi non modali per servire come un secondo "frame".
Jeffrey,

Ottima risposta e risposta dettagliata anche se devo essere d'accordo con @kleopatra su questo .. Una volta ho avuto un'applicazione con oltre un centinaio di schermate in cui gli utenti volevano confrontare i dati di output da più schermate / stesso schermo con input diversi. Abbiamo creato un sistema di finestre personalizzato per consentirci di farlo. Gli utenti erano più a loro agio con 2 JFrame da tenere uno accanto all'altro;)
javatarz

Mentre capisco la tua tesi, preferirei comunque avere tutto in uno JFramee un genitore grande JTabbedPane; ma con la possibilità di aprire una seconda finestra (o anche di più) in cui il layout può essere diverso, offrendo quindi un comportamento ibrido in cui gli amanti della SDI sono felici e anche quelli della MDI. In ogni caso, ho sempre considerato JInternalFrameun modello orribile che ti dà tutti gli inconvenienti di entrambi i mondi. La flessibilità che offrono fa schifo e consuma molto spazio prezioso sullo schermo senza scopi reali.
Guillaume Polet,

Sono d'accordo che SDI è talvolta appropriato (e gli utenti spesso lo preferiscono). C'è ancora un altro inconveniente, e finora non ho trovato alcuna soluzione alternativa, sfortunatamente: ognuno ha JFramela propria icona sulla barra delle applicazioni. A volte questo è esattamente quello che vuoi, ma a volte no. In WinAPI questo è facile da configurare, ma in Swing sembra che non possa essere fatto.
Suma,

@suma in quel caso penso che opterei per un JDialogover a JFrame.
ryvantage

51

Vorrei contrastare l'argomento "non user friendly" con un esempio di cui sono appena stato coinvolto.

Nella nostra applicazione abbiamo una finestra principale in cui gli utenti eseguono vari "programmi" come schede separate. Per quanto possibile, abbiamo cercato di mantenere la nostra applicazione in questa singola finestra.

Uno dei "programmi" che eseguono presenta un elenco di report che sono stati generati dal sistema e l'utente può fare clic su un'icona su ciascuna riga per aprire una finestra di dialogo del visualizzatore di report. Questo visualizzatore mostra l'equivalente delle pagine A4 verticale / orizzontale del report, quindi agli utenti piace che questa finestra sia abbastanza grande, quasi riempiendo gli schermi.

Alcuni mesi fa abbiamo iniziato a ricevere richieste dai nostri clienti per rendere modeste queste finestre del visualizzatore di report, in modo che potessero aprire più report contemporaneamente.

Per qualche tempo ho resistito a questa richiesta poiché non pensavo che fosse una buona soluzione. Tuttavia, la mia mente è cambiata quando ho scoperto come gli utenti stessero aggirando questa "carenza" del nostro sistema.

Stavano aprendo un visualizzatore, usando la funzione 'Salva con nome' per salvare il rapporto come PDF in una directory specifica, usando Acrobat Reader per aprire il file PDF, e avrebbero fatto lo stesso con il rapporto successivo. Avrebbero più lettori Acrobat in esecuzione con i vari output di report che volevano guardare.

Così ho ceduto e reso lo spettatore non modale. Ciò significa che ogni visualizzatore ha un'icona nella barra delle attività.

Quando l'ultima versione è stata rilasciata a loro la scorsa settimana, la risposta schiacciante da loro è che AMANO. È stato uno dei nostri più recenti recenti miglioramenti del sistema.

Quindi vai avanti e dici ai tuoi utenti che ciò che vogliono è male, ma alla fine non ti farà alcun favore.

ALCUNE NOTE:

  • Sembra essere la migliore pratica usare JDialog per queste finestre non modali
  • Usa i costruttori che usano il nuovo ModalityTypeanziché l' modalargomento booleano . Questo è ciò che dà a queste finestre di dialogo l'icona della barra delle applicazioni.
  • Per le finestre di dialogo non modali, passare un genitore nullo al costruttore, ma localizzarlo in relazione alla finestra "principale".
  • La versione 6 di Java su Windows ha un bug, il che significa che la tua finestra principale può diventare "sempre in primo piano" senza che tu te lo dica. Aggiorna alla versione 7 per risolvere questo problema

6
Questa è esattamente anche la mia esperienza. Se c'è una cosa di cui sono certo, è che stai facendo qualcosa di sbagliato quando le persone cercano di aggirare la tua facilità d'uso per fare qualunque cosa vogliano davvero fare. La funzionalità è re.
ryvantage

Un modo per aggirare il problema è consentire l'apertura di più JFrame, tutti con la stessa funzionalità, ma per impostazione predefinita tutto viene eseguito in un'unica finestra. Questo in realtà consente all'utente di scegliere tra SDI o MDI.
Guillaume Polet,

Scusate? Puoi spiegare meglio la tua soluzione, per favore? Come può essere una singola finestra E più finestre? Abbiamo una finestra principale in cui viene eseguita l'applicazione principale, ma a volte è necessario aprire le finestre di dialogo e talvolta tali finestre di dialogo (in base ai requisiti dell'utente) devono essere non modali. Stabilire regole che l'interfaccia dovrebbe essere in questo modo o che sta per scavare un grosso buco per te.
DuncanKinnear

1
@GuillaumePolet Sono d'accordo con Duncan, puoi spiegare cosa vuoi dire un po 'di più? Condivido la sua confusione
Ungeheuer il

Penso che ciò che intende dire sia che l'utente potrebbe avviare più copie dell'applicazione (il "JFrame") ma all'interno di ognuna di esse è SDI. Tuttavia, la nostra applicazione client è un client molto denso, quindi questo sarebbe un approccio affamato di risorse.
DuncanKinnear

20

Trasforma un jInternalFrame nel frame principale e rendilo invisibile. Quindi puoi usarlo per ulteriori eventi.

jInternalFrame.setSize(300,150);
jInternalFrame.setVisible(true);

19

È passato un po 'di tempo dall'ultima volta che tocco lo swing, ma in generale è una cattiva pratica farlo. Alcuni dei principali svantaggi che vengono in mente:

  • È più costoso: dovrai allocare molte più risorse per disegnare un JFrame quell'altro tipo di contenitore di finestre, come Dialog o JInternalFrame.

  • Non facile da usare: non è facile navigare in un gruppo di JFrame uniti, sembrerà che la tua applicazione sia un insieme di applicazioni incoerente e mal progettato.

  • È facile da usare JInternalFrame Questo è un po 'retorico, ora è molto più semplice e altre persone più intelligenti (o con più tempo libero) di quanto abbiamo già pensato attraverso il modello Desktop e JInternalFrame, quindi consiglierei di usarlo.


7
Non hai lo stesso effetto per l'utente quando usi anche multiplo JInternalFrame? Personalmente, non sono d'accordo con l'uso di JInternalFrame's! CardLayoutè una vera benedizione!
Branislav Lazic,

4
Sono d'accordo con @ brano88. JInternalFramenon offre alcun vantaggio in nessuno dei tre casi che hai citato (1. dov'è l'evidenza JInternalFramepiù leggera di JFrame? 2. I tuoi messaggi di posta JInternalFrameelettronica potrebbero essere altrettanto ingombra / disordinati / uniti insieme come un gruppo di messaggi di posta JFrameelettronica 3. Come è JInternalFramepiù facile? È il lo stesso codice esatto, tranne per il fatto che uno è contenuto all'interno di uno JDesktopPanee uno è contenuto nell'area dello schermo naturale. Mi sembrano ugualmente complessi.)
ryvantage

1
1. JFrame è un componente hevyweight paragonato a JInternalFrame che è un peso leggero. 2. Hai mai visto un'app che contiene tonnellate di finestre contemporaneamente per funzionare? IDE, Browser, anche nell'applicazione finanziaria è un obiettivo mantenerlo nello stesso ambito. 3. Ho trovato JIF molto facile da usare in passato e ovviamente non ho lamentele nel scegliere il componente che meglio si adatta a uno scenario
Necronet

4
1. Mi piacerebbe vedere la prova di questo. Entrambi sono oggetti, entrambi sono JComponents, entrambi hanno strutture quasi identiche, tranne uno è reso su a JDesktope uno no. Ancora una volta, scusa, ma credo che tu stia speculando sul "peso" di JFrame. 2. Le mie applicazioni usano SDI e i miei clienti sono molto contenti. Tuttavia, hai detto "un sacco di finestre", il che, naturalmente, farebbe schifo. Ma il mio punto è questo: "un sacco di" JInternalFramefarebbe schifo altrettanto male! Se stai dicendo che i JIF ti consentono di essere un designer UI sciatto, allora è terribile. Un disordine disordinato è un disordine disordinato, sia JF che JIF.
ryvantage

2
"ovviamente scegli il componente che meglio si adatta a uno scenario"
Necronet,

10

Cattiva pratica sicuramente. Uno dei motivi è che non è molto 'user-friendly' per il fatto che ognuno JFramemostra una nuova icona sulla barra delle applicazioni. Il controllo di più JFrames ti farà strappare i capelli.

Personalmente, userei ONE JFrameper il tuo tipo di applicazione. I metodi di visualizzazione di più cose dipendono da te, ce ne sono molti. CanvasES, JInternalFrame, CardLayout, anche JPanels possibilmente.

Più oggetti JFrame = dolore, difficoltà e problemi.


9
hmm ... niente di nuovo rispetto alla risposta accettata, afaics?
Kleopatra, il

5
"Ogni JFrame mostra una nuova icona nella barra delle attività", vale solo per Windows! Su Mac OS X ogni applicazione ha una sola icona dock, indipendentemente da quante finestre ha aperto, ed è comune per le applicazioni avere più finestre di livello superiore.
Rolf,

8

Penso che usare più Jframes non sia una buona idea.

Invece possiamo usare JPanels più di uno o più JPanelnello stesso JFrame.

Inoltre possiamo passare da uno all'altro JPanel. Quindi ci dà la libertà di mostrare più che sulle cose nel JFrame.

Per ognuno JPanelpossiamo progettare cose diverse e tutto ciò JPanelpuò essere visualizzato sul singolo JFramealla volta.

Per alternare JPanelutilizzare questo JMenuBarcon JMenuItemsciascuno JPanelo "JButton for eachJPanel".

Più di una JFramenon è una buona pratica, ma non c'è nulla di sbagliato se vogliamo più di una JFrame.

Ma è meglio cambiarne uno JFrameper le nostre diverse esigenze piuttosto che avere più JFrames.


5

Se le cornici avranno le stesse dimensioni, perché non creare la cornice e passare la cornice come riferimento invece.

Dopo aver superato il frame, puoi decidere come popolarlo. Sarebbe come avere un metodo per calcolare la media di un insieme di cifre. Vuoi creare il metodo più e più volte?


1
Questo è fondamentalmente fare ciò che Cardlayout e JTabbedPane possono fare, ma farlo al contrario e rendere il codice eccessivamente complesso mentre si dispone di una soluzione pulita e semplice per ottenere la stessa cosa.
Guillaume Polet,

4

Non è una buona pratica ma anche se si desidera utilizzarlo, è possibile utilizzare il modello singleton come relativo. Ho usato i modelli singleton nella maggior parte del mio progetto è buono.


3
Il modello Singleton è un incubo. Qualsiasi progetto che desideri ridimensionare dovrebbe cercare di evitare il modello singleton a tutti i costi.
Guillaume Polet,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.