2012-06-03 33 views
8

大多數佈局管理器沒有參數構造函數(也就是說,您可以創建一個帶有new FlowLayout()的FlowLayout,帶有new GridLayout()的GridLayout,帶有new GridBagLayout()的GridBagLayout等)。但是,BoxLayout要求您傳遞將要管理的容器和組件佈置的軸。爲什麼你需要用BoxLayout調用setLayout?

我的問題是:既然你已經告訴佈局管理器哪個組件來鋪陳,爲什麼你需要寫

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

,而不是僅僅在第一線?

我快速瀏覽了一下the BoxLayout source code,看到我使用的構造函數(第178-185行)沒有調用target.setLayout(this)或任何類型的東西。看起來似乎只是增加這一點非常簡單。是否有一個原因,它沒有包含在Swing庫中?

如果它的事項,我使用

Java版本1.7.0

的Java(TM)SE運行時環境(建立1.7.0-B147)

上Win7Pro 。

謝謝!


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爲[SSCCE](http://sscce.org/) – trashgod

回答

5

Container必須存在才能傳遞給BoxLayout。通常,一個寫這樣的事情:

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

這是很有誘惑力的最後兩行合併,但最小驚訝的原則表明,佈局的構造不應以其他方式改變容器的狀態。

Convenienly javax.swing.Box提供了「使用BoxLayout對象作爲佈局管理器的輕量級容器。「

public class Box extends JComponent implements ... { 

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

現在一行將做:

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

有一個相關的例子[這裏](http://stackoverflow.com/a/6076340/230513)。 – trashgod

+1

這是有道理的,謝謝你告訴我關於盒子。 – wchargin

+0

不客氣,作爲參考,該設計與[此處]討論的原理一致(http://stackoverflow.com/a/3404369/230513)。 – trashgod

4

BoxLayout可以確保佈局方法應用到正確的容器。它強制執行是在構造函數中指定的同一個容器中的各種方法被使用,如layoutContainer(Container target)preferredLayoutSize(Container target),等它歸結到checkContainer()方法,做了驗證:

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

BoxLayout可能實現一些緩存有關容器的詳細信息並嘗試維護狀態,因此無法共享。

編輯:

BoxLayout實現LayoutManager2.invalidateLayout()如果它確實重置其緩存的細節。其他佈局實現遵循相同的模式。例如,GroupLayoutOverlayLayout也需要在其構造函數中使用容器參數。

+0

我明白,它不能被共享然而。 ,因爲它不能共享,所以組件必須將其設置爲其佈局似乎是合乎邏輯的 - *爲什麼* BoxLayout只是在構造函數中調用'setLayout(container)'?另外,爲什麼請不要讓其他經理執行此操作? – wchargin

+0

@WChargin BoxLayout使用構造函數中指定的參數來驗證和應用限制。另請參閱我對其他管理器的編輯。 – tenorsax

+0

JComponents實現setLa你可能會感興趣...... – mKorbel

相關問題