9

ほとんどのレイアウト マネージャーには、引数のないコンストラクターがあります (つまり、 を使用して FlowLayout を作成したり、 を使用しnew FlowLayout ()て GridLayout を作成したり、 を使用new GridLayout ()して GridBagLayout を作成したりできますnew GridBagLayout ())。ただし、BoxLayout管理するコンテナーと、コンポーネントを配置する軸の両方を渡す必要があります。

私の質問は次のとおりです。レイアウトマネージャーにレイアウトするコンポーネントを既に伝えているのに、なぜ書く必要があるのですか?

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

最初の行だけではなく?

ソース コードをざっと見てみるとBoxLayout使用しているコンストラクター (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);
    }
}
4

2 に答える 2

5

Containerに渡す前に が存在している必要がありますBoxLayout。通常、次のように書きます。

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

最後の 2 行を結合したくなるかもしれませんが、最小の驚きの原則は、レイアウトのコンストラクターがコンテナーの状態を変更してはならないことを示唆しています。

便利なことに、「オブジェクトをレイアウト マネージャーとしてjavax.swing.Box使用する軽量コンテナー」を提供します。BoxLayout

public class Box extends JComponent implements ... {

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

これで、1 行で実行できます。

Box myBox = new Box(BoxLayout.Y_AXIS);
于 2012-06-03T07:41:40.157 に答える
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実装はおそらくコンテナーに関する詳細をキャッシュし、状態を維持しようとするため、共有できません。

編集:

BoxLayoutLayoutManager2.invalidateLayout()を実装し、キャッシュされた詳細をリセットします。他のレイアウトの実装も同じパターンに従います。たとえば、GroupLayoutOverlayLayoutのコンストラクターには、container 引数も必要です。

于 2012-06-03T05:26:21.667 に答える