2012-06-03 17 views
8

La maggior parte dei gestori di layout ha costruttori senza argomenti (ovvero, è possibile creare un FlowLayout con new FlowLayout(), un GridLayout con new GridLayout(), un GridBagLayout con new GridBagLayout() e così via). Tuttavia, BoxLayout richiede di passare sia il contenitore che gestirà sia l'asse lungo il quale i componenti dovrebbero essere disposti.Perché è necessario invocare setLayout con BoxLayout?

La mia domanda è: quanto si sta già dicendo il gestore di layout quale componente per disporre, perché avete bisogno di scrivere

BoxLayout bl = new BoxLayout(myPanel, BoxLayout.Y_AXIS); 
myPanel.setLayout(bl); 

anziché solo la prima linea?

Ho dato un'occhiata veloce a the BoxLayout source code e ho visto che il costruttore che uso (righe 178-185) non effettua una chiamata a target.setLayout(this) o qualcosa del genere. Sembra che sarebbe davvero semplice aggiungerlo. C'è una ragione per cui non è inclusa nella libreria Swing?

Se è importante, sto usando

versione Java 1.7.0

Java (TM) SE Runtime Environment (build 1.7.0-B147)

su Win7Pro .

Grazie!


SSCCE:

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JButton; 

public class BoxLayoutSSCCE extends JFrame { 

    // Change this to see what I mean 
    public static final boolean CALL_SET_LAYOUT = true; 

    public BoxLayoutSSCCE() { 
     super("Box Layout SSCCE"); 
     JPanel panel = new JPanel(); 
     BoxLayout bl = new BoxLayout(panel, BoxLayout.Y_AXIS); 
     if (CALL_SET_LAYOUT) { 
      panel.setLayout(bl); 
     } 
     panel.add(new JButton("Button 1")); 
     panel.add(new JButton("Button 2")); 
    } 

    public static void main (String[] args) { 
     BoxLayoutSSCCE blsscce = new BoxLayoutSSCCE(); 
     blsscce.pack(); 
     blsscce.setVisible(true); 
    } 
} 
+1

+1 per [sscce] (http://sscce.org/) – trashgod

risposta

5

Il Container deve esistere prima che possa essere passato a BoxLayout. In genere si scrive qualcosa di simile:

JPanel myPanel = new JPanel(); 
BoxLayout bl = new BoxLayout(myPanel, BoxLayout.Y_AXIS); 
myPanel.setLayout(bl); 

E 'forte la tentazione di combinare le ultime due righe, ma il principio del minimo stupore suggerisce che il costruttore di layout non dovrebbe alterare in altro modo lo stato del contenitore.

Convenientemente, javax.swing.Box fornisce "Un contenitore leggero che utilizza un oggetto BoxLayout come gestore di layout."

public class Box extends JComponent implements ... { 

    public Box(int axis) { 
     super(); 
     super.setLayout(new BoxLayout(this, axis)); 
    } 
} 

Ora una sola linea farà:

Box myBox = new Box(BoxLayout.Y_AXIS); 
+0

C'è un esempio correlato [qui] (http://stackoverflow.com/a/6076340/230513). – trashgod

+1

Questo ha senso, e grazie per avermi parlato di Box. – wchargin

+0

Prego; per riferimento, il design è coerente con il principio discusso [qui] (http://stackoverflow.com/a/3404369/230513). – trashgod

4

BoxLayout fa in modo che i metodi di layout vengono applicate al contenitore corretto. Si impone che lo stesso contenitore specificato nel costruttore è utilizzato in vari metodi, come layoutContainer(Container target), preferredLayoutSize(Container target), ecc Si riduce il metodo checkContainer() che fa la verifica:

void checkContainer(Container target) { 
    if (this.target != target) { 
     throw new AWTError("BoxLayout can't be shared"); 
    } 
} 

BoxLayout attuazione probabilmente memorizza alcuni dettagli sul contenitore e cerca di mantenere lo stato, quindi non può essere condiviso.

EDIT:

BoxLayout implementa LayoutManager2.invalidateLayout() dove non resetta i suoi dettagli memorizzati nella cache. Altre implementazioni di layout seguono lo stesso schema. Ad esempio, GroupLayout e OverlayLayout richiedono anche argomenti contenitore nei relativi costruttori.

+0

Capisco che non può essere condivisa Tuttavia.. dato che non può essere condiviso, sembra logico che il componente debba impostarlo come layout - * perché * non 'BoxLayout' chiama semplicemente' setLayout (container) 'nel costruttore? Inoltre, perché non altri gestori lo applicano? – wchargin

+0

@WChargin L'argomento specificato nel costruttore viene utilizzato da BoxLayout per verificare e applicare la restrizione.Vedere anche la mia modifica su altri gestori. – tenorsax

+0

JComponents implementa setLa potresti essere interessante ... – mKorbel

Problemi correlati