0

左揃えのフロー レイアウト マネージャーでレイアウトされた、任意の数の JLabels を含む JPanel を作成しました。これを FlowPanel と呼びましょう。

各 FlowPanel には深さがあり、これらの FlowPanel を任意の数だけ積み重ねて、それぞれを固定量 * 深さでインデントしたいと考えています。最終的な目標は、水平スクロールバーではなく、垂直スクロールバー (必要な場合) を持つ JScrollPane 内にこれらの積み重ねられたパネルを表示することです。

FlowPanels を GridBagLayout で積み重ねてみましたが、垂直に積み重ねて好きなようにインデントするのは簡単でしたが、幅を正しくする方法がわかりません。つまり、FlowPanels はメイン パネルの右側からはみ出しており、表示されている幅には注意を払っていません。

setPreferredSize、setSize を使用して、GridBagConstraints をいじってみました...運が悪いです。

助けてください!:)

問題を示すためのサンプルコード。このコードには 2 つの問題があります。2. FlowPanels に含まれる要素が多すぎると、行が画面の右側からスクロールします。

public class FlowExample {

public static void main(String[] args) throws Exception {
    JFrame frame = new JFrame();

    StackPanel stackPanel = new StackPanel();
    frame.getContentPane().setLayout(new BorderLayout());
    frame.getContentPane().add(
            new JScrollPane(stackPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER),
            BorderLayout.CENTER);

    frame.setLocation(200, 200);
    frame.setSize(300, 300);
    frame.setVisible(true);

    List<FlowPanel> content = new ArrayList<FlowPanel>();
    for (int i = 0; i < 20; i++) {
        FlowPanel flowPanel = new FlowPanel((int) (4 * Math.random()));
        for (int j = 0; j < (int) (20 * Math.random()); j++) {
            flowPanel.add(new JLabel("label " + j));
        }
        content.add(flowPanel);
        stackPanel.layoutGUI(content);
        Thread.sleep(1000);
    }

    System.in.read();
    System.exit(0);
}
}

class StackPanel extends JPanel {

public StackPanel() {
    setLayout(new BorderLayout());
}

public void layoutGUI(final List<FlowPanel> content) {
    if (!SwingUtilities.isEventDispatchThread()) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                layoutGUI(content);
            }
        });
        return;
    }

    JPanel mainPanel = new JPanel();
    mainPanel.setLayout(new GridLayout(content.size(), 1));
    for (FlowPanel flowPanel : content) {
        flowPanel.setBorder(BorderFactory.createEmptyBorder(0, flowPanel.getDepth() * 10, 0, 0));
        mainPanel.add(flowPanel);
    }

    removeAll();
    add(mainPanel, BorderLayout.CENTER);
    revalidate();
}
}

class FlowPanel extends JPanel {

private int depth;

public FlowPanel(int depth) {
    setLayout(new FlowLayout(FlowLayout.LEFT));
    this.depth = depth;
}

public int getDepth() {
    return depth;
}
}

メイン パネルのレイアウトに GridBagLayout を使用するサンプル コードを次に示します。これは私が得た最良の結果ですが、ご覧のとおり、FlowPanels はまだラップされていません...

    JPanel mainPanel = new JPanel();
    mainPanel.setLayout(new GridBagLayout());
    GridBagConstraints constraints = new GridBagConstraints();
    constraints.weightx = 1;
    constraints.gridwidth = GridBagConstraints.REMAINDER;
    constraints.anchor = GridBagConstraints.LINE_START;

    for (FlowPanel flowPanel : content) {
        System.out.println("setting border to " + flowPanel.getDepth());
        flowPanel.setBorder(BorderFactory.createEmptyBorder(0, flowPanel.getDepth() * 10, 0, 0));
        mainPanel.add(flowPanel, constraints);
    }

    constraints.weighty = 1;
    mainPanel.add(new JPanel(), constraints);

    removeAll();
    add(mainPanel, BorderLayout.CENTER);
    revalidate();
4

1 に答える 1

1

GridLayout はすべてを画面に合わせようとするため、リストを渡すことで毎回高さを再調整します。最初から大きな定数を設定することで、十分なスペースを確保するように指示しています。この行を変更してみてください:

mainPanel.setLayout(new GridLayout(content.size(), 1));

mainPanel.setLayout(new GridLayout(500, 1));

スクロールバーが最初から表示されないようにするには、代わりに BoxLayout を使用します。

JPanel mainPanel = new JPanel();
Box box = Box.createVerticalBox();
mainPanel.add( box );
for (FlowPanel flowPanel : content) {
    flowPanel.setBorder(BorderFactory.createEmptyBorder(0, flowPanel.getDepth() * 10, 0, 0));
    box.add(flowPanel);
}
removeAll();
add(mainPanel, BorderLayout.CENTER);
revalidate();

ラッピングの問題は、setPreferredSize のみを考慮した FlowLayout にあります。既存のコードを使用して、動的なサイズ変更要件を犠牲にして、すべてに適合するように 1 つの優先サイズを設定できます。または、過去にcamickrのWrapLayoutを使用したことがあり、うまく機能します。

http://tips4java.wordpress.com/2008/11/06/wrap-layout/

そのままで、WrapLayout は、ラップが必要かどうかに応じて異なる推奨サイズを返します。

1)。最小幅変数を追加

private int minWidth = -1;

2)。最後の行の 'layoutSize' メソッドを変更します。

if(minWidth != -1) {
    dim.width = minWidth;
}
return dim;

それが完了したら、サンプル コードへの唯一の変更は FlowPanel コンストラクターにあります。

public FlowPanel(int depth) {
    WrapLayout layout = new WrapLayout(FlowLayout.LEFT);
    layout.setMinWidth(300);
    setLayout(layout);
    setSize(new Dimension(300, 30));
}
于 2012-05-01T00:42:22.430 に答える