不同尺寸组件的 LayoutManager,无需编码绝对位置

LayoutManager for different sized components without coding absolute positions

我正在尝试创建一些 UI 但不知道如何使用 LayoutManger

就像图片中显示的那样紫色分量有固定的宽度和高度但是粘在角落里。 8 和 4 具有固定高度和可变高度,2 和 6 具有固定高度和可变宽度。中间组件 (9) 需要可变宽度和高度。

这 8 个组件像边框一样工作,中间的组件需要根据父组件的大小调整大小。我可以使用空布局对绝对位置进行编码。但我建议不要使用空布局。

如何使用可用于此目的的布局管理器 布局来做到这一点?我需要使用多个布局吗?

更新

我已经按照 Andrew 的建议尝试了 GridBagLayout 的一些东西,但我仍然需要一点帮助来理解它是如何工作的。这是我的代码

 import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GridLayoutTest {
    
    
    
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        JPanel jPanel1 = new JPanel();
        jPanel1.setLayout(new GridBagLayout());
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        
        
        
        JButton button;

        GridBagConstraints c = new GridBagConstraints();

        button = new JButton("1");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.FIRST_LINE_START;
        c.gridx = 0;
        c.gridy = 0;
        jPanel1.add(button, c);

        button = new JButton("2");
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 1.0;
        c.gridx = 1;
        c.gridy = 0;
        jPanel1.add(button, c);

        button = new JButton("3");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.FIRST_LINE_END;
        c.gridx = 2;
        c.gridy = 0;
        jPanel1.add(button, c);

        button = new JButton("4");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.LINE_START;
        c.weighty = 1.0;
        c.gridx = 0;
        c.gridy = 1;
        jPanel1.add(button, c);

        //Panel
        JPanel panel = new JPanel();
        panel.setBackground(Color.green.darker());
        c.fill = GridBagConstraints.BOTH;
        c.weightx = 0.0;
        //c.weightx = 1.0;
        c.gridx = 1;
        c.gridy = 1;
        jPanel1.add(panel, c);

        button = new JButton("5");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.LINE_END;
        c.weighty = 1.0;
        c.gridx = 2;
        c.gridy = 1;
        jPanel1.add(button, c);

        button = new JButton("6");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.LAST_LINE_START;
        c.gridx = 0;
        c.gridy = 2;
        jPanel1.add(button, c);

        button = new JButton("7");
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 1.0;
        c.gridx = 1;
        c.gridy = 2;
        jPanel1.add(button, c);

        button = new JButton("8");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.LAST_LINE_END;
        c.gridx = 2;
        c.gridy = 2;
        jPanel1.add(button, c);
        
        
        frame.add(jPanel1);
        
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setSize(500, 500);
        frame.setVisible(true);
        
    }
   
}

另一个选项是 JGoodies FormLayout. I have been using this in combination with JFormDesigner 来满足我所有的布局需求,因为基本上永远如此。它涵盖了我 95% 的用例。剩下的5%是BorderLayout和绝对定位(空布局)。

解决复杂计算任务的一种常见策略是将它们分解为小的、定义明确的可管理任务。分而治之。 这也适用于 gui:您可以将设计分解为小的、易于布局的容器。 在这种情况下,可以通过使用 BoxLayoutBorderLayout:

来实现所需的布局
import java.awt.*;
import javax.swing.Box.Filler;
import javax.swing.*;


public class FramedContent extends JPanel{

    private static final int FRAME_WIDTH = 35, CONTENT_SIZE = 300, BORDER_SIZE = 1;
    private static final Color CORNER_COLOR = Color.MAGENTA, RULLER_COLOR = Color.BLUE,
                                CONTENT_COLOR = Color.GREEN, BORDER_COLOR = Color.WHITE;
    FramedContent(){
        setLayout(new BorderLayout());
        add(header(), BorderLayout.NORTH);
        add(center(), BorderLayout.CENTER);
        add(header(), BorderLayout.SOUTH);
    }

    private JPanel header(){
        JPanel hExpandPane = new JPanel();
        hExpandPane.setLayout(new BoxLayout(hExpandPane, BoxLayout.X_AXIS));
        hExpandPane.add(corner());
        hExpandPane.add(hRuller());
        hExpandPane.add(corner());
        return hExpandPane;
    }

    private JComponent corner(){
        Dimension d = new Dimension(FRAME_WIDTH, FRAME_WIDTH);
        Filler filler = new Filler(d, d, d);
        filler.setBackground(CORNER_COLOR);
        filler.setBorder(BorderFactory.createLineBorder(BORDER_COLOR, BORDER_SIZE));
        filler.setOpaque(true);
        return filler;
    }

    private JComponent hRuller(){
        Dimension d = new Dimension(0,FRAME_WIDTH);
        Filler filler = new Filler(d, d, new Dimension(Short.MAX_VALUE, FRAME_WIDTH));
        filler.setBackground(RULLER_COLOR);;
        filler.setOpaque(true);
        return filler;
    }

    private JPanel center(){
        JPanel vExpandPane = new JPanel();
        vExpandPane.setLayout(new BorderLayout());
        vExpandPane.add(vRuller(), BorderLayout.WEST);
        vExpandPane.add(content(), BorderLayout.CENTER);
        vExpandPane.add(vRuller(), BorderLayout.EAST);
        return vExpandPane;
    }

    private JComponent vRuller(){
        Dimension d = new Dimension(FRAME_WIDTH, 0);
        Filler filler = new Filler(d, d, new Dimension(FRAME_WIDTH, Short.MAX_VALUE));
        filler.setBackground(RULLER_COLOR);
        filler.setOpaque(true);
        return filler;
    }

    private JPanel content(){
        JPanel content = new JPanel(new GridBagLayout());// GridBagLayout used just to center the content
        content.setBackground(CONTENT_COLOR);
        content.add(new JLabel("Your Content Goes Here"));
        content.setPreferredSize(new Dimension(CONTENT_SIZE,CONTENT_SIZE));
        return content;
    }

    public static void createWindow()   {
        JFrame frame = new JFrame("Framed content");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.add(new FramedContent());
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        createWindow();
    }
}

我创建了以下 GUI。

我为网格的每个元素设置了所有六个 GridBagConstraint(anchor、fill、gridx、gridy、weightx、weighty)。这样,我可以更轻松地跟踪每个元素的值。

这是我使用的完整可运行代码。换句话说,一个最小的、可重现的例子。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

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

public class GridBagLayoutGUI implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new GridBagLayoutGUI());
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("GridBagLayout GUI");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(createMainPanel(), BorderLayout.CENTER);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JPanel createMainPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setPreferredSize(new Dimension(300, 300));

        JButton button;

        GridBagConstraints c = new GridBagConstraints();

        button = new JButton("1");
        c.fill = GridBagConstraints.NONE;
        c.anchor = GridBagConstraints.FIRST_LINE_START;
        c.weightx = 0.0d;
        c.weighty = 0.0d;
        c.gridx = 0;
        c.gridy = 0;
        panel.add(button, c);

        button = new JButton("2");
        c.fill = GridBagConstraints.HORIZONTAL;
        c.anchor = GridBagConstraints.CENTER;
        c.weightx = 1.0d;
        c.weighty = 0.0d;
        c.gridx = 1;
        c.gridy = 0;
        panel.add(button, c);

        button = new JButton("3");
        c.fill = GridBagConstraints.NONE;
        c.anchor = GridBagConstraints.FIRST_LINE_END;
        c.weightx = 0.0d;
        c.weighty = 0.0d;
        c.gridx = 2;
        c.gridy = 0;
        panel.add(button, c);

        button = new JButton("4");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.LINE_START;
        c.weightx = 0.0d;
        c.weighty = 1.0d;
        c.gridx = 0;
        c.gridy = 1;
        panel.add(button, c);

        // Panel
        JPanel innerPanel = new JPanel();
        innerPanel.setBackground(Color.green.darker());
        c.fill = GridBagConstraints.BOTH;
        c.anchor = GridBagConstraints.CENTER;
        c.weightx = 1.0d;
        c.weighty = 1.0d;
        c.gridx = 1;
        c.gridy = 1;
        panel.add(innerPanel, c);

        button = new JButton("5");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.LINE_END;
        c.weightx = 0.0d;
        c.weighty = 1.0d;
        c.gridx = 2;
        c.gridy = 1;
        panel.add(button, c);

        button = new JButton("6");
        c.fill = GridBagConstraints.NONE;
        c.anchor = GridBagConstraints.LAST_LINE_START;
        c.weightx = 0.0d;
        c.weighty = 0.0d;
        c.gridx = 0;
        c.gridy = 2;
        panel.add(button, c);

        button = new JButton("7");

        c.fill = GridBagConstraints.HORIZONTAL;
        c.anchor = GridBagConstraints.CENTER;
        c.weightx = 1.0d;
        c.weighty = 0.0d;
        c.gridx = 1;
        c.gridy = 2;
        panel.add(button, c);

        button = new JButton("8");
        c.fill = GridBagConstraints.NONE;
        c.anchor = GridBagConstraints.LAST_LINE_END;
        c.weightx = 0.0d;
        c.weighty = 0.0d;
        c.gridx = 2;
        c.gridy = 2;
        panel.add(button, c);

        return panel;
    }

}