Devo evitare l'uso di metodi set (Preferred | Maximum | Minimum) Size in Java Swing?


481

Più volte sono stato criticato per aver suggerito l'uso dei seguenti metodi:

  1. setPreferredSize
  2. setMinimumSize
  3. setMaximumSize

sui Swingcomponenti. Non vedo alcuna alternativa al loro uso quando voglio definire le proporzioni tra i componenti visualizzati. Mi è stato detto questo:

Con i layout la risposta è sempre la stessa: utilizzare un LayoutManager adatto

Ho cercato un po 'sul Web, ma non ho trovato alcuna analisi completa sull'argomento. Quindi ho le seguenti domande:

  1. Devo evitare completamente l'uso di questi metodi?
  2. I metodi sono stati definiti per un motivo. Quindi quando dovrei usarli? In quale contesto? Per quali scopi?
  3. Quali sono esattamente le conseguenze negative dell'uso di questi metodi? (Posso solo pensare di aggiungere portabilità tra sistemi con diversa risoluzione dello schermo).
  4. Non credo che nessun LayoutManager possa soddisfare esattamente tutte le esigenze di layout desiderate. Devo davvero implementare un nuovo LayoutManager per ogni piccola variazione del mio layout?
  5. Se la risposta a 4 è "sì", ciò non porterà a una proliferazione di classi LayoutManager che diventeranno difficili da mantenere?
  6. In una situazione in cui devo definire le proporzioni tra i figli di un Componente (ad esempio, child1 dovrebbe usare il 10% di spazio, child2 40%, child3 50%), è possibile ottenerlo senza implementare un LayoutManager personalizzato?

Risposte:


236
  1. Devo evitare completamente l'uso di questi metodi?

    Sì per il codice dell'applicazione.

  2. I metodi sono stati definiti per un motivo. Quindi quando dovrei usarli? In quale contesto? Per quali scopi?

    Non lo so, personalmente lo considero un incidente di progettazione API. Leggermente forzato da componenti composti con idee speciali sulle dimensioni dei bambini. "Leggermente", perché avrebbero dovuto implementare le loro esigenze con un LayoutManager personalizzato.

  3. Quali sono esattamente le conseguenze negative dell'uso di questi metodi? (Posso solo pensare di aggiungere portabilità tra i sistemi con una diversa risoluzione dello schermo.)

    Alcuni motivi tecnici (incompleti e sfortunatamente i collegamenti sono interrotti a causa della migrazione di SwingLabs su java.net) sono ad esempio menzionati nelle Regole (hehe) o nel collegamento @bendicott trovato nel suo commento alla mia risposta . Socialmente, ponendo tonnellate di lavoro sul tuo sfortunato compagno che deve mantenere il codice e deve rintracciare un layout rotto.

  4. Non credo che nessun LayoutManager possa soddisfare esattamente tutte le esigenze di layout desiderate. Devo davvero implementare un nuovo LayoutManager per ogni piccola variazione del mio layout?

    Sì, ci sono LayoutManager abbastanza potenti da soddisfare un'ottima approssimazione a "tutte le esigenze di layout". I tre grandi sono JGoodies FormLayout, MigLayout, DesignGridLayout. Quindi no, in pratica, raramente scrivi LayoutManager ad eccezione di semplici ambienti altamente specializzati.

  5. Se la risposta a 4 è "sì", ciò non porterà a una proliferazione di classi LayoutManager che diventeranno difficili da mantenere?

    (La risposta a 4 è "no".)

  6. In una situazione in cui devo definire le proporzioni tra i figli di un Componente (ad esempio, il figlio 1 dovrebbe usare il 10% di spazio, il figlio 2 il 40%, il figlio 3 il 50%), è possibile ottenerlo senza implementare un LayoutManager personalizzato?

    Nessuno dei Big-Three può, nemmeno GridBag (non si è mai preso la briga di dominare davvero, troppi problemi per troppo poca potenza).


4
Non sono del tutto sicuro di essere d'accordo con questo consiglio in almeno due situazioni. 1) Componenti con rendering personalizzato 2) Utilizzo di a JEditorPanecon HTML che non suggerisce di per sé una larghezza. OTOH Non sono sicuro di aver perso qualcosa. Esaminerò attentamente le risposte sul thread, ma ero interessato a ricevere commenti, in particolare su quest'ultimo caso.
Andrew Thompson,

2
@Andrew Thompson 1) comps personalizzati: è il comp stesso che è responsabile per la restituzione di suggerimenti di layout utili, se non l'impl è buggy 2) anche i core comp sono buggy ;-) 3) Non mi dispiace lo spazio bianco (anche se non lo era intenzionale questa volta, grazie :-)
Kleopatra il

8
Non posso credere che la risposta accettata sia quella che dice di evitare di usare i metodi setXXX (). A volte ti servono semplicemente per fornire un suggerimento al gestore del layout. Se stai progettando un pannello, dovresti assolutamente sentirti libero di usare questi metodi quando necessario. Dicendo che penso che se usi il gestore del layout appropriato ti ritroverai a non aver bisogno di questi metodi molto spesso, ma a volte ne hai semplicemente bisogno. Prova a mettere un JComboBox o un JSpinner in un X_AXIS BoxLayout e non usarli, credi che troverai che hai bisogno di setMaximumSize () lì.
Michael,

5
@Michael no, non ne ho assolutamente bisogno - la risposta è sempre quella di usare un LayoutManager decente e fare qualsiasi modifica al livello manageriale (rispetto al livello componente)
Kleopatra

5
Continui a dire "usa un LayoutManager decente e digli quali dimensioni vuoi" in tutto lo stackoverflow, ma non dai mai esempi specifici di un LayoutManager "decente". E nessuno dei gestori standard consente di controllare direttamente le dimensioni.
Ti Strga,

100

Alcune euristiche:

  • Non utilizzare set[Preferred|Maximum|Minimum]Size()quando si intende veramente eseguire l'override get[Preferred|Maximum|Minimum]Size(), come si potrebbe fare per creare il proprio componente, mostrato qui .

  • Non utilizzare set[Preferred|Maximum|Minimum]Size()quando si può fare affidamento su un componente accuratamente ignorato getPreferred|Maximum|Minimum]Size, come mostrato qui e sotto.

  • Utilizzare set[Preferred|Maximum|Minimum]Size()per derivare post- validate()geometria, come mostrato di seguito e qui .

  • Se un componente non ha dimensioni preferite, ad esempio JDesktopPane, potrebbe essere necessario dimensionare il contenitore, ma tale scelta è arbitraria. Un commento può aiutare a chiarire l'intento.

  • Prendi in considerazione layout alternativi o personalizzati quando scopri che dovresti passare in rassegna molti componenti per ottenere dimensioni derivate, come menzionato in questi commenti .

inserisci qui la descrizione dell'immagine

import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.KeyboardFocusManager;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

/**
 * @see /programming/7229226
 * @see /programming/7228843
 */
public class DesignTest {

    private List<JTextField> list = new ArrayList<JTextField>();
    private JPanel panel = new JPanel();
    private JScrollPane sp = new JScrollPane(panel);

    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                DesignTest id = new DesignTest();
                id.create("My Project");
            }
        });
    }

    private void addField(String name) {
        JTextField jtf = new JTextField(16);
        panel.add(new JLabel(name, JLabel.LEFT));
        panel.add(jtf);
        list.add(jtf);
    }

    private void create(String strProjectName) {
        panel.setLayout(new GridLayout(0, 1));
        addField("First Name:");
        addField("Last Name:");
        addField("Address:");
        addField("City:");
        addField("Zip Code:");
        addField("Phone:");
        addField("Email Id:");
        KeyboardFocusManager.getCurrentKeyboardFocusManager()
            .addPropertyChangeListener("permanentFocusOwner",
            new FocusDrivenScroller(panel));
        // Show half the fields
        sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        sp.validate();
        Dimension d = sp.getPreferredSize();
        d.setSize(d.width, d.height / 2);
        sp.setPreferredSize(d);

        JInternalFrame internaFrame = new JInternalFrame();
        internaFrame.add(sp);
        internaFrame.pack();
        internaFrame.setVisible(true);

        JDesktopPane desktopPane = new JDesktopPane();
        desktopPane.add(internaFrame);

        JFrame frmtest = new JFrame();
        frmtest.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frmtest.add(desktopPane);
        frmtest.pack();
        // User's preference should be read from java.util.prefs.Preferences
        frmtest.setSize(400, 300);
        frmtest.setLocationRelativeTo(null);
        frmtest.setVisible(true);
        list.get(0).requestFocusInWindow();
    }

    private static class FocusDrivenScroller implements PropertyChangeListener {

        private JComponent parent;

        public FocusDrivenScroller(JComponent parent) {
            this.parent = parent;
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            Component focused = (Component) evt.getNewValue();
            if (focused != null
                && SwingUtilities.isDescendingFrom(focused, parent)) {
                parent.scrollRectToVisible(focused.getBounds());
            }
        }
    }
}

2
non sono d'accordo (come avresti potuto immaginare :-) con il ragionamento di "fattori esterni": le proprietà XXSize hanno lo scopo di esprimere solo bisogni interni . Modificare quelli dall'esterno è un uso improprio, noto anche come hacking. Se vuoi un frame (interno o J-) con una dimensione specifica relativa al suo preferito ... ridimensiona il frame, non il contenuto
Kleopatra,

2
@kleopatra: solo per essere un po 'insistente: se i metodi setXXSize non devono mai essere usati dall'esterno, perché non sono stati dichiarati privati ​​o protetti? Non è questa una mancanza di design? Il modificatore pubblico non dice implicitamente all'utente che può usare quei metodi?
Heisenbug,

2
Sono d'accordo con @kleopatra: setPreferredSize()sostituisce sempre il calcolo del componente con una scelta arbitraria.
trashgod,

1
@trashgod +100 per te Penso che non ci siano problemi con l'override di questi metodi, anche chiamandoli (ma ovviamente questo significherebbe che hai un componente personalizzato, quindi l'override sarebbe meglio)
David Kroukamp

5
@DavidKroukamp: grazie. Rinvio alla maggiore esperienza di Kleopatra, ma vedo il valore nell'esaminare criticamente la visione contraria.
trashgod,

47

Devo evitare completamente l'uso di questi metodi?

No, non esistono prove formali che suggeriscano che la chiamata o l'override di questi metodi non sia consentita. In effetti, Oracle afferma che questi metodi vengono utilizzati per fornire suggerimenti sulla dimensione: http://docs.oracle.com/javase/tutorial/uiswing/layout/using.html#sizealignment .

Possono anche essere sovrascritti (che è la migliore pratica per Swing) quando si estende un componente Swing (anziché chiamare il metodo sull'istanza del componente personalizzato)

Soprattutto, indipendentemente da come si specificano le dimensioni del componente, assicurarsi che il contenitore del componente utilizzi un gestore di layout che rispetti le dimensioni richieste del componente.

I metodi sono stati definiti per un motivo. Quindi quando dovrei usarli? In quale contesto? Per quali scopi?

Quando è necessario fornire suggerimenti dimensionali personalizzati al gestore di layout dei contenitori in modo che il componente sia disposto correttamente

Quali sono esattamente le conseguenze negative dell'uso di questi metodi? (Posso solo pensare di aggiungere portabilità tra sistemi con diversa risoluzione dello schermo).

  • Molti gestori di layout non prestano attenzione alle dimensioni massime richieste per un componente. Tuttavia, BoxLayoute SpringLayoutfallo. Inoltre, GroupLayoutoffre la possibilità di impostare esplicitamente la dimensione minima, preferita o massima, senza toccare il componente.

  • Assicurati di aver davvero bisogno di impostare la dimensione esatta del componente. Ogni componente Swing ha una dimensione preferita diversa, a seconda del carattere utilizzato e dell'aspetto grafico. Pertanto, avere una dimensione impostata potrebbe produrre vari aspetti dell'interfaccia utente su sistemi diversi

  • a volte si possono riscontrare problemi con GridBagLayoute campi di testo, in cui se la dimensione del contenitore è inferiore alla dimensione preferita, viene utilizzata la dimensione minima, che può causare una sostanziale riduzione dei campi di testo.

  • JFramenon impone l'overriden getMinimumSize()invocando solo le setMinimumSize(..)sue opere

Non credo che nessun LayoutManager possa soddisfare esattamente tutte le esigenze di layout desiderate. Devo davvero implementare un nuovo LayoutManager per ogni piccola variazione del mio layout?

Se implementando intendi usare allora sì. Nessuno LayoutMangerpuò gestire tutto, ognuno LayoutManagerha i suoi pro e contro, quindi ognuno può essere usato insieme per produrre il layout finale.

Riferimento:


3
fornire suggerimenti di dimensioni personalizzate che è una contraddizione in sé: fornire suggerimenti di dimensionamento (in px!) è il compito esclusivo del componente. Li calcola sulla base di dettagli sullo stato interno che nessun'altra parte tranne se stessa può conoscere (né può tenere traccia di). Dal punto di vista del cliente, i mezzi di personalizzazione possono essere un LayoutManager adatto e / o specializzare api sul componente che consente di configurare i requisiti di dimensione in termini di proprietà "semantiche" relative alla dimensione, numero di righe / colonne in un componente di testo
Kleopatra

3
@kleopatra Mi piacerebbe ancora sapere perché Oracle ci dice quindi come utilizzare questi metodi e il modo corretto di usarli. Potremmo avere le nostre preferenze, ma non possiamo dire che i progettisti affermino che non verrà utilizzato quando non ci sono prove che lo suggeriscano. Ma è per questo che ho messo su la grazia per vedere se attirerebbe altri che potrebbero fornire informazioni da una fonte credibile in cui l'oracolo afferma di non usare affatto questi metodi (rendendo così una cattiva pratica se lo fai, ad esempio setMinimumSize deve essere chiamato cose come JSplitPane ecc., questo può essere visto nel tutorial Oracle sui pannelli divisi
David Kroukamp,

4
@ David: sono arrivato a vedere i setXxxSizemetodi come una bandiera rossa che potrei finire qui , anche quando i documenti lo suggeriscono. Ho quasi sempre dovuto ignorato getXxxSize, dove si ha accesso alla geometria richiesta; e anche brevi esempi vengono riciclati più di quanto io voglia pensare. +1 per menzionare la variazione tra i gestori di layout e citare il tutorial.
trashgod,

1
D'oh, nel mio commento sopra, intendevo citare la risposta qui .
trashgod,

13
+1 "No, non esistono prove formali per suggerire che non sia consentito chiamare o ignorare questi metodi." Spot on. Il post taggato come risposta è semplice BS.
TT.

25

Ci sono molte buone risposte qui, ma voglio aggiungere un po 'di più sui motivi per cui dovresti normalmente evitarli (la domanda è appena tornata in un argomento duplicato):

Con poche eccezioni, se stai usando questi metodi probabilmente stai perfezionando la tua GUI per avere un bell'aspetto su un aspetto grafico specifico (e con le tue impostazioni specifiche del sistema, ad esempio il tuo font desktop preferito, ecc.). I metodi stessi non sono intrinsecamente malvagi, ma i motivi tipici per usarli sono . Non appena inizi a sintonizzare posizioni e dimensioni dei pixel in un layout, corri il rischio che la tua GUI si rompa (o almeno, sembri male) su altre piattaforme.

Ad esempio, prova a modificare l'aspetto e le impostazioni predefinite dell'applicazione. Anche solo con le opzioni disponibili sulla tua piattaforma, potresti essere sorpreso da quanto male possano essere resi i risultati.

Quindi, nel nome di mantenere la tua GUI funzionale e di bell'aspetto su tutte le piattaforme (ricorda, uno dei principali vantaggi di Java è la sua multipiattaforma), dovresti fare affidamento su gestori di layout, ecc., Per regolare automaticamente le dimensioni di i componenti in modo che vengano visualizzati correttamente al di fuori del proprio ambiente di sviluppo specifico.

Detto questo, puoi certamente concepire situazioni in cui questi metodi sono giustificati. Ancora una volta, non sono intrinsecamente malvagi, ma il loro utilizzo è normalmente una grande bandiera rossa che indica potenziali problemi della GUI. Assicurati solo di essere consapevole dell'alto potenziale di complicanze se / quando le usi, e cerca sempre di pensare se esiste un'altra soluzione indipendente dai tuoi problemi - il più delle volte scoprirai che questi i metodi non sono necessari.

A proposito, se ti senti frustrato con i gestori di layout standard, ce ne sono molti di buona terza parte gratuiti e open source, ad esempio JGoodies 'FormLayout o MigLayout. Alcuni costruttori di GUI hanno persino il supporto integrato per i gestori di layout di terze parti - l'editor GUI di WindowBuilder di Eclipse, ad esempio, viene fornito con supporto per FormLayoute MigLayout.


2
+1 una risposta premurosa - solo in disaccordo con il fatto che non sono intrinsecamente malvagi semplicemente perché lo sono :-) In genere, i clienti esterni non hanno alcuna possibilità di indovinare - e i semplici presupposti sono più vicini che gli estranei possono ottenere - suggerimenti a metà del percorso corretti: solo i componenti stessi hanno sempre tutte le informazioni per restituire qualcosa di utile. E dal momento in cui gli estranei interferiscono, è loro responsabilità tenere aggiornati quei suggerimenti che non possono.
Kleopatra,

1
Bene, sai, ho un punto di vista più "le pistole non uccidono le persone, le persone uccidono le persone" di questo tipo di cose. :) Se qualcuno usa questi metodi, devono essere consapevoli di cose come i punti positivi sollevati sull'uso imprevedibile dei suggerimenti di layout (motivo per cui le situazioni in cui questi metodi sono appropriati sono davvero rare).
Jason C

Penso che l'impostazione della dimensione preferita non sia affatto una grande bandiera rossa. Non impostarlo è invece una grande bandiera rossa. Lasciami elaborare. Il gestore del layout, non importa quanto sia intelligente, non ha idea della funzione logica di un widget GUI. Ad esempio, il gestore del layout non può distinguere tra un JTextField per l'immissione del codice postale e un JTextField per l'immissione di un nome. Allo stesso modo, non è possibile distinguere tra un pulsante dello strumento accanto a un JTextField o un grande pulsante OK nella parte inferiore di un modulo. Pertanto, è necessario un set di widget migliore o sono necessari alcuni suggerimenti per il dimensionamento, no?
Gee Bee,

@GeeBee No, questo è un ottimo esempio di bandiera rossa, in effetti. Quello che dovresti fare è usare JTextField.setColumnsper impostare il conteggio delle colonne, che regola di conseguenza la dimensione preferita. Se lo fai, setPreferredSizeallora stai codificando una dimensione, che romperà i tuoi layout a seconda della dimensione del carattere della piattaforma. Ecco alcuni campi di testo in un layout a griglia con setColumnschiamati in modo appropriato . Per i pulsanti, utilizzare layout / pesi della griglia appropriati per controllare le dimensioni.
Jason C

@GeeBee E ora, fatto ciò correttamente, notate come diminuiscono le larghezze dei campi di testo quando diminuisco la dimensione del carattere: i.snag.gy/ZULulh.jpg . Anche cambiando la dimensione del carattere al volo ora funziona automaticamente, piuttosto che tu, diciamo, dover ricalcolare tutte le larghezze dei campi di testo e chiamare esplicitamente setPreferredSize di nuovo per ciascuno, tutto ciò che devi fare è invalidare il layout e le loro dimensioni si adatteranno.
Jason C

20

Se hai problemi con i layout in Java Swing, allora posso consigliare vivamente i JGoodies FormLayoutforniti gratuitamente come parte della libreria freeware Forms di Karsten Lentzsch qui .

Questo gestore di layout molto popolare è estremamente flessibile e consente di sviluppare interfacce utente Java molto raffinate.

Troverete la documentazione di Karsten in qui , e alcuni piuttosto buona documentazione da Eclipse qui .


16

Questi metodi sono capiti male dalla maggior parte delle persone. Non dovresti assolutamente ignorare questi metodi. Spetta al responsabile del layout se rispettano questi metodi. Questa pagina ha una tabella che mostra quali gestori di layout onorano quale di questi metodi:

http://thebadprogrammer.com/swing-layout-manager-sizing/

Ho scritto il codice Swing per 8+ anni e i gestori di layout inclusi nel JDK hanno sempre soddisfatto le mie esigenze. Non ho mai avuto bisogno di un gestore di layout di terze parti per realizzare i miei layout.

Dirò che non dovresti provare a dare suggerimenti al gestore del layout con questi metodi finché non sei sicuro di averne bisogno. Fai il tuo layout senza dare alcun suggerimento sul dimensionamento (es. Lascia che il responsabile del layout faccia il suo lavoro) e quindi puoi apportare correzioni minori se necessario.


1
o c'è un leggero malinteso (da parte tua) o incomprensione (da parte mia), fai la tua scelta :-) Continui a ripetere (qui, nel tuo blog, nella tua risposta relativa a BoxLayout) il set XXSize come importante - in realtà il LayoutManager è interessato o meno a XXSize, ovvero il suggerimento di dimensionamento indipendente da come è stato realizzato (calcolo interno del componente o forzato manualmente dal codice dell'applicazione)
Kleopatra

1
Non sono sicuro di aver capito cosa stai arrivando qui. Ho menzionato sopra che i metodi XXSize () sono solo suggerimenti. Non vedo davvero nulla di male nel dare un piccolo suggerimento a un gestore di layout, se necessario. Nel mio codice swing, troverai un metodo setXXSize () occasionale. Non molti, ma ogni tanto trovo che sono necessari. JComboBox e JSpinner necessitano spesso di suggerimenti. Soprattutto un JComboBox che viene popolato dopo che è stato realizzato. Sembra che tu sia contrario a qualsiasi uso di questi metodi e non so perché. (forse mi manca quella barca su questo immagino).
Michael,

5
non i metodi sono i suggerimenti, le proprietà sono: i componenti dovrebbero riportare qualcosa di ragionevole per tutti i suggerimenti, alcuni (come fi JComboBox) no - nel restituire maxInteger o giù di lì. Questo è un bug e dovrebbe essere risolto dalla combo. Per quanto riguarda la tua abitudine: assicurati di essere lontano quando il collega del manutentore deve ripulirlo :) I suggerimenti codificati tendono a rovinare il layout al minimo cambiamento e sono difficili da rilevare come motivo per un layout rotto.
Kleopatra,

15

In una situazione in cui devo definire le proporzioni tra i figli di un componente (il figlio 1 dovrebbe usare il 10% di spazio, il figlio2 il 40%, il figlio 3 il 50%), è possibile farlo senza implementare un gestore di layout personalizzato?

Forse GridBagLayoutsoddisfaresti le tue esigenze. Oltre a ciò, sul Web ci sono molti gestori di layout e scommetto che ce n'è uno che si adatta alle tue esigenze.


Grazie per la risposta. Devo presumere che intendessi anche: "non usare affatto setPreferredSize", giusto?
Heisenbug,

1
GridBagLayout utilizza i vincoli, in cui è possibile specificare il "peso" sia in X che in Y per un determinato componente, in modo che LayoutManager possa decidere cosa fare con lo spazio extra su un ridimensionamento. MA hai ancora bisogno / puoi usare setPreferredSize per determinare la dimensione preferita di ciascun componente, nota che "preferito" non significa che sarà sempre onorato. Per casi speciali potrebbe essere necessario impostare setMinimumSize e setMaximumSize comunque. Non sono cattivi , non comprarli. docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html
マ ル ち ゃ ん だ よ

5

Lo vedo in modo diverso rispetto alla risposta accettata.

1) Devo evitare completamente l'uso di questi metodi?

Non evitare mai! Sono lì per esprimere i vincoli di dimensione dei tuoi componenti al gestore del layout. Puoi evitare di usarli se non stai utilizzando alcun gestore di layout e provare a gestire il layout visivo da solo.

Sfortunatamente, Swing non ha dimensioni predefinite ragionevoli. Tuttavia, invece di impostare le dimensioni di un componente, è meglio OOP discendere il proprio componente con impostazioni predefinite ragionevoli. (In tal caso, si chiama setXXX nella classe discendente). In alternativa, è possibile ignorare i metodi getXXX per lo stesso effetto.

2) I metodi sono stati definiti per un motivo. Quindi quando dovrei usarli? In quale contesto? Per quali scopi?

Sempre. Quando si crea un componente, impostarne le dimensioni minime / preferite / massime realistiche in base all'utilizzo di quel componente. Ad esempio, se si dispone di un JTextField per l'immissione di simboli di paesi come il Regno Unito, la sua dimensione preferita deve essere ampia per adattarsi a due caratteri (con il carattere corrente, ecc.), Ma probabilmente non ha senso lasciarlo crescere più grande. Dopo tutto, i simboli del paese sono due caratteri. Al contrario, se si dispone di un JTextField per l'immissione, ad esempio, di un nome cliente, può avere una dimensione preferita come la dimensione pixel per 20 caratteri, ma può aumentare di dimensioni se il layout viene ridimensionato, quindi impostare la dimensione massima su più. Allo stesso tempo, avere un JTextField largo 0px è inutile, quindi imposta una dimensione minima realistica (direi la dimensione in pixel di 2 caratteri).

3) Quali sono esattamente le conseguenze negative dell'utilizzo di questi metodi?

(Posso solo pensare di aggiungere portabilità tra sistemi con diversa risoluzione dello schermo).

Nessuna conseguenza negativa. Questi sono suggerimenti per il gestore del layout.

4) Non credo che nessun LayoutManager possa soddisfare esattamente tutte le esigenze di layout desiderate.

Devo davvero implementare un nuovo LayoutManager per ogni piccola variazione del mio layout?

No, sicuramente no. L'approccio abituale è quello di mettere in cascata diversi layout manager di base come layout orizzontale e verticale.

Ad esempio, il layout seguente:

<pre>
+--------------+--------+
| ###JTABLE### | [Add]  | 
| ...data...   |[Remove]|
| ...data...   |        |
| ...data...   |        |
+--------------+--------+
</pre>

sta avendo due parti. Le parti sinistra e destra sono un layout orizzontale. La parte destra è un JPanel aggiunto al layout orizzontale, e questo JPanel ha un layout verticale che dispone i pulsanti in verticale.

Naturalmente, questo può diventare complicato con un layout di vita reale. Pertanto, i gestori di layout basati su griglia come MigLayout sono molto meglio se stai per sviluppare qualcosa di serio.

5) Se la risposta a 4 è "sì", ciò non porterà a una proliferazione di classi LayoutManager che diventeranno difficili da mantenere?

No, sicuramente non dovrai sviluppare gestori di layout, a meno che tu non abbia bisogno di qualcosa di molto speciale.

6) In una situazione in cui devo definire le proporzioni ...

tra i figli di un componente (ad esempio, child1 dovrebbe usare il 10% di spazio, child2 40%, child3 50%), è possibile farlo senza implementare un LayoutManager personalizzato?

Fondamentalmente, una volta che le dimensioni preferite sono impostate correttamente, potresti non voler fare nulla in percentuale. Semplicemente, poiché le percentuali sono inutili (ad esempio, è inutile avere un JTextField il 10% delle dimensioni della finestra - poiché è possibile ridurre la finestra in modo che JTextField diventi largo 0px o espandere la finestra in modo che JTextField si trovi su due schermi in un configurazione multi-display).

Ma a volte potresti usare le percentuali per controllare le dimensioni di blocchi più grandi della tua gui (pannelli, per esempio).

È possibile utilizzare JSplitPane in cui è possibile preimpostare il rapporto tra i due lati. In alternativa, è possibile utilizzare MigLayout che consente di impostare tali vincoli in percentuale, pixel e altre unità.


Veramente? Questo era a 0? Questo è meglio della risposta accettata che ha 100+ up. Questo dice sostanzialmente "Non dovrai mai usare setPreferredSize!" che è TERRIBILE. Nella mia linea di lavoro, ci sono MOLTI requisiti di dimensioni specifiche, come "I pulsanti sui touchscreen devono essere [X] di [Y] con [M] x [N] spaziatura tra" requisito di sicurezza. btnBar.setPreferredSize( dimTouchBtn );è il modo migliore per farlo. Semplice, senza bisogno di un gestore di layout personalizzato. Uso principalmente GridBagLayoutcon alcuni BorderLayoute BoxLayout, annidando quando è conveniente. Questa è una combinazione forte e facile da usare.
Loduwijk,

Ero frettoloso nel mio commento sopra. Questa è stata la prima risposta che ho visto dopo la risposta accettata. Perché SO non ordina più per voto conta più? Pensavo che fosse una delle ragioni principali per il conteggio dei voti in origine. Resto comunque il commento originale; questa è una delle risposte migliori. Tranne il punto 6: quello non eccezionale. Ci sono molte (la minoranza può ancora essere un gran numero) di motivi per ridimensionare, e GridBagLayout lo supporta bene nella maggior parte dei casi che ho avuto.
Loduwijk,

Penso che ridimensionare vs. non ridimensionare non debba essere trattato come una decisione religiosa. Ci sono casi d'uso in cui nessuno vuole mai ridimensionare nulla, ad esempio se si sviluppa una GUI per un chiosco, con una risoluzione fissa preimpostata. Se hai obiettivi diversi, come i display HMI industriali e il caso di "pulsanti", sì, devi avere almeno 1 cm per 1 cm per un pulsante su un touchscreen. In questo caso, il DPI dello schermo imposta la modalità di ridimensionamento. Altri input come i campi di testo potrebbero non essere affatto ridimensionati verticalmente, e talvolta anche il ridimensionamento orizzontale (come un codice postale) è inutile.
Gee Bee,

0

Devo evitare completamente l'uso di questi metodi? Non direi "evitali". Direi che se pensi di averne bisogno, probabilmente stai facendo qualcosa di sbagliato. Le dimensioni dei componenti sono determinate nel contesto. Ad esempio, le dimensioni dei componenti di testo sono determinate dal numero di righe e colonne specificate, combinato con il carattere che potresti aver scelto. La dimensione del pulsante e dell'etichetta sarà la dimensione del grafico, se impostato, o lo spazio necessario per visualizzare il testo impostato. Ogni componente ha una dimensione naturale e i gestori del layout useranno quelli per disporre tutto senza che sia necessario specificare le dimensioni. L'eccezione principale è JScrollPane, che ha una dimensione indipendente da qualunque cosa contenga. Per quelli, a volte chiamerò setSize()e lascerò che quella dimensione determini la dimensione iniziale della finestra, chiamandoJFrame.pack(). Di solito, lascio che la dimensione della finestra determini la dimensione di JScrollPane. L'utente determinerà la dimensione della finestra. Molti gestori di layout ignorano comunque le dimensioni impostate, quindi spesso non fanno molto bene.

I metodi sono stati definiti per un motivo. Quindi quando dovrei usarli? In quale contesto? Per quali scopi? Credo che siano stati aggiunti per fornire suggerimenti ai gestori del layout. Potrebbero essere stati scritti per motivi storici, perché i gestori del layout erano nuovi e le persone non si fidavano completamente di loro. Conosco alcuni sviluppatori che hanno evitato i gestori di layout e hanno posizionato tutto manualmente, solo perché non volevano preoccuparsi di imparare un nuovo paradigma. È un'idea terribile.

Quali sono esattamente le conseguenze negative dell'uso di questi metodi? (Posso solo pensare di aggiungere portabilità tra sistemi con diversa risoluzione dello schermo). Sono inefficaci e producono layout errati, con oggetti che vengono schiacciati o allungati a dimensioni non naturali. E i layout saranno fragili. Le modifiche alle dimensioni della finestra a volte interrompono il layout e mettono le cose nei posti sbagliati.

Non credo che nessun LayoutManager possa soddisfare esattamente tutte le esigenze di layout desiderate. Devo davvero implementare un nuovo LayoutManager per ogni piccola variazione del mio layout? Non dovresti "implementare" un nuovo LayoutManager. È necessario creare un'istanza di quelli esistenti. Uso spesso diversi gestori di layout in un'unica finestra. Ogni JPanel avrà il proprio gestore di layout. Alcune persone si oppongono ai layout nidificati, perché sono difficili da mantenere. Quando li uso, do a ciascuno il proprio metodo di creazione per rendere più facile vedere ciò che ognuno fa. Ma non ho mai "implementato" un gestore di layout. Li ho solo istanziati.

Se la risposta a 4 è "sì", ciò non porterà a una proliferazione di classi LayoutManager che diventeranno difficili da mantenere? Se stai implementando nuove classi di gestione layout per leggere variazioni nel layout, le stai usando in modo errato. Se stai solo implementando nuovi gestori di layout, probabilmente stai facendo qualcosa di sbagliato. L'unica volta che ho esteso una classe LayoutManager, è stato quello di aggiungere un dispositivo di scorrimento dello zoom a un JScrollPane.

In una situazione in cui devo definire le proporzioni tra i figli di un Componente (ad esempio, child1 dovrebbe usare il 10% di spazio, child2 40%, child3 50%), è possibile ottenerlo senza implementare un LayoutManager personalizzato? JSplitPane ha un modo per specificare la percentuale che ogni componente dovrebbe ottenere. Il divisore è mobile per impostazione predefinita, ma puoi disattivarlo se lo desideri. Non uso molto questa funzione. Di solito ho alcuni componenti che occupano una dimensione impostata e il resto dello spazio è occupato da un riquadro di scorrimento. Le dimensioni del riquadro di scorrimento verranno adattate alle dimensioni della finestra. Se si hanno due riquadri di scorrimento affiancati, è possibile inserirli in un JSplitPane e specificare la percentuale di nuovo spazio assegnato a ciascuno man mano che l'utente espande e contrae le finestre.

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.