网格袋布局 25% 50% 25%

GridBagLayout 25% 50% 25%

这是防止 GridBagLayout 单元格相对于其内容调整大小的正确方法吗?

gbl_panel.columnWidths = new int[] {1000, 4000, 1000};

SSCCE

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.AbstractListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.EmptyBorder;

public class GridBagLayoutTemplate extends JFrame {

private JPanel contentPane;

public GridBagLayoutTemplate() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 450, 300);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    contentPane.setLayout(new BorderLayout(0, 0));
    setContentPane(contentPane);


    JPanel panel = new JPanel();
    contentPane.add(panel);

    GridBagLayout gbl_panel = new GridBagLayout();
    gbl_panel.rowHeights = new int[] {1};
    gbl_panel.columnWidths = new int[] {1000, 4000, 1000};
    gbl_panel.columnWeights = new double[]{1.0, 4.0, 1.0};
    gbl_panel.rowWeights = new double[]{1.0};
    panel.setLayout(gbl_panel);

    JScrollPane scrollPane = new JScrollPane();
    GridBagConstraints gbc_scrollPane = new GridBagConstraints();
    gbc_scrollPane.insets = new Insets(0, 0, 0, 5);
    gbc_scrollPane.fill = GridBagConstraints.BOTH;
    gbc_scrollPane.gridx = 0;
    gbc_scrollPane.gridy = 0;
    panel.add(scrollPane, gbc_scrollPane);

    JList list = new JList();
    scrollPane.setViewportView(list);
    list.setModel(new AbstractListModel() {
        String[] values = new String[] {"qwe"};
        public int getSize() {
            return values.length;
        }
        public Object getElementAt(int index) {
            return values[index];
        }
    });

    JScrollPane scrollPane_1 = new JScrollPane();
    GridBagConstraints gbc_scrollPane_1 = new GridBagConstraints();
    gbc_scrollPane_1.insets = new Insets(0, 0, 0, 5);
    gbc_scrollPane_1.fill = GridBagConstraints.BOTH;
    gbc_scrollPane_1.gridx = 1;
    gbc_scrollPane_1.gridy = 0;
    panel.add(scrollPane_1, gbc_scrollPane_1);

    JList list_1 = new JList();
    scrollPane_1.setViewportView(list_1);
    list_1.setModel(new AbstractListModel() {
        String[] values = new String[] {"qwe"};
        public int getSize() {
            return values.length;
        }
        public Object getElementAt(int index) {
            return values[index];
        }
    });

    JScrollPane scrollPane_2 = new JScrollPane();
    GridBagConstraints gbc_scrollPane_2 = new GridBagConstraints();
    gbc_scrollPane_2.fill = GridBagConstraints.BOTH;
    gbc_scrollPane_2.gridx = 2;
    gbc_scrollPane_2.gridy = 0;
    panel.add(scrollPane_2, gbc_scrollPane_2);

    JList list_3 = new JList();
    scrollPane_2.setViewportView(list_3);
    list_3.setModel(new AbstractListModel() {
        String[] values = new String[] {"qweqweqweqweqwqweqweqweqweqweqweqweqweqwqweqweqweqweqweqweqweqwqweqweqweqweqweqweqweqweqwqweqweqweqweqweqweqweqweqwqweqweqweqweqwqweqweqweqweqweqweqweqweqwqweqweqweqweqweqweqweqweqwqweqweqweqwe"};
        public int getSize() {
            return values.length;
        }
        public Object getElementAt(int index) {
            return values[index];
        }
    });
}
}

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                GridBagLayoutTemplate frame = new GridBagLayoutTemplate();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

有意思。我以前从未见过这样的方法。

通常使用 GridBagLayout 这样:

  1. 每个组件根据其首选大小
  2. 分配space
  3. 如果额外 space 可用,则根据分配给每个组件的 weightx(权重)值将 space 分配给每个组件。

因此只有额外的space分配在25% 50% 25%的比例。

您的方法似乎忽略了组件的首选大小,并以 25% 50% 25% 的比例分配 space。

但是,您首先需要进行以下更改以获得正确的比率:

//gbl_panel.columnWidths = new int[] {1000, 4000, 1000};
//gbl_panel.columnWeights = new double[]{1.0, 4.0, 1.0};
gbl_panel.columnWidths = new int[] {1000, 2000, 1000};
gbl_panel.columnWeights = new double[]{1.0, 2.0, 1.0};

下面是我用来测试将 space 分配给 400 像素宽的面板上的组件的简化代码:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class GridBagLayoutRelative extends JPanel
{
    public GridBagLayoutRelative()
    {
        setPreferredSize( new Dimension(400, 300) );

        //  Components will be allocated relative widths of 25%, 50%, 25%
        //  (preferred width will be ignored)

        GridBagLayout gbl = new GridBagLayout();
        //gbl.columnWidths = new int[] {25, 50, 25}; // doesn't work
        gbl.columnWidths = new int[] {250, 500, 250}; // larger value in same ratio
        gbl.columnWeights = new double[] {25.0, 50.0, 25.0};
        setLayout(gbl);

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.BOTH;
        gbc.weighty = 1.0;
        gbc.gridy = 0;

        JPanel red = new JPanel();
        red.setBackground( Color.RED );
        red.setPreferredSize( new Dimension(30, 200) );
        gbc.gridx = 0;
        add(red, gbc);

        JPanel green = new JPanel();
        green.setBackground( Color.GREEN );
        green.setPreferredSize( new Dimension(40, 200) );
        gbc.gridx = 1;
        add(green, gbc);

        JPanel blue = new JPanel();
        blue.setBackground( Color.BLUE );
        blue.setPreferredSize( new Dimension(50, 200) );
        gbc.gridx = 2;
        add(blue, gbc);

        addComponentListener( new ComponentAdapter()
        {
            @Override
            public void componentResized(ComponentEvent e)
            {
                System.out.println( e.getComponent().getSize() );

                for (Component c: getComponents())
                    System.out.println( "\t" + c.getSize() );
            }
        });
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("GridBagLayout Relative");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new GridBagLayoutRelative());
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args) throws Exception
    {
        java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
    }
}

结果是:

java.awt.Dimension[width=100,height=300]
java.awt.Dimension[width=200,height=300]
java.awt.Dimension[width=100,height=300]

所以我会说这种方法有效。

注意:如果您有兴趣,过去我建议您可以使用专为此类布局设计且更易于使用的Relative Layout

使用 RelativeLayout 以上行为将通过使用复制:

RelativeLayout rl = new RelativeLayout(RelativeLayout.X_AXIS);
rl.setFill(true);
setLayout( rl );

JPanel red = new JPanel();
red.setBackground( Color.RED );
red.setPreferredSize( new Dimension(30, 200) );
add(red, new Float(25));

JPanel green = new JPanel();
green.setBackground( Color.GREEN );
green.setPreferredSize( new Dimension(40, 200) );
add(green, new Float(50));

JPanel blue = new JPanel();
blue.setBackground( Color.BLUE );
blue.setPreferredSize( new Dimension(50, 200) );
add(blue, new Float(25));