java GUI布局建议

java GUI layout suggestion

public class AFS {
    public JPanel afs(final Fields input){
        JPanel titlePanel = new JPanel();

        //Title fields
        JLabel afs = new JLabel("Statement", Label.LEFT);

        Label mm = new Label("month ", Label.LEFT);
        Label my = new Label("Year ", Label.LEFT);

        //first line
        titlePanel.add(afs);
        titlePanel.add(mm);
        titlePanel.add(input.MENTRY);
        titlePanel.add(my);
        titlePanel.add(input.YENTRY);
        titlePanel.setPreferredSize(null);

        //Left Panels
        JPanel sb = new JPanel();
        JPanel entry = new JPanel();
        entry.setLayout(new BoxLayout(entry, BoxLayout.Y_AXIS));
        entry.setAlignmentX(Component.LEFT_ALIGNMENT);
        entry.add(new Label("Service "));
        entry.add(input.s);
        entry.add(new Label("Amount "));
        entry.add(input.a);
        entry.add(new Label("Counter "));
        entry.add(input.o);
        entry.add(new Label("Division "));
        entry.add(input.d);

        sb.add(entry);


        JPanel holderPanel = new JPanel();
        holderPanel.setLayout(new BoxLayout(holderPanel, BoxLayout.Y_AXIS));
        holderPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
        holderPanel.add(titlePanel);
        holderPanel.add(sb);

        JButton start = new JButton("Save Current");
        start.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                ScriptAction action = new ScriptAction();
                action.saveAll(input,1);
            }
        });
        holderPanel.add(start); 
        return holderPanel;
    }

我有上面代码的简短版本。 当前布局如下所示:

但我希望布局看起来像(绘画编辑)。

我已经尝试使用 gridLayout 作为条目进行交换,它将显示 2 行,但 gridlayout 仍会将所有内容居中对齐(包括标题和 header)。此外,按钮跨度将跨越整个底部。我想知道是否有任何建议的方法可以做到这一点?

您需要使用 layout managers 的组合来实现所需的输出:

调整大小前/调整大小后

在这种情况下有 3 个主要部分:

  • 顶部窗格(使用 Box 将一些文本左对齐,一些文本右对齐)
  • 中间窗格(使用 GridBagLayout 将组件放置在图像中,也许 GridLayout 使用适当的插图也可以工作)
  • 底部窗格(使用默认 JPanel 的布局:FlowLayout

顶部窗格也使用 2 个 JPanel,第一个单独用于标签 Statement,另一个 FlowLayout 与其他 4 个组件右对齐,如per this answer BoxLayout 不符合我们 JTextField 的首选尺寸。因此,解决方法是将它们包装在另一个 JPanel 中,然后将 JPanelStatement 标签一起包装。

中间窗格也出现了类似的问题,它需要使用 2 个 JPanels:一个用于包裹在另一个更大的窗格中的字段,该窗格包含它和底部的 JButtonSave Current).我们可以通过添加带有 gridx = 2JButton 和带有 counterdivision 标签的 gridy = 2 以及 gridx = 3 上的字段来实现类似的输出gridx = 4 分别(而不是 2 & 3)但是我们需要添加 gbc.insets 以在顶部和底部添加具有高值的插图......这取决于你使用 :)

生成上述输出的代码如下:

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class FormSample {
    private JFrame frame;
    private JPanel topRightPane;
    private JPanel centerPane;
    private JPanel centerWithButtonPane;
    private JPanel buttonsPane;

    private JTextField monthField;
    private JTextField yearField;

    private JTextField serviceField;
    private JTextField amountField;
    private JTextField counterField;
    private JTextField divisionField;

    private static final int LEFT_MARGIN = 50; //Increase / Decrease to add extra space between components
    private static final int RIGHT_MARGIN = LEFT_MARGIN;

    //Change insets accordingly to add extra space between components (top, left, bottom, right)
    private static final Insets leftInsets = new Insets(0, LEFT_MARGIN, 0, 0);
    private static final Insets rightInsets = new Insets(0, 0, 0, RIGHT_MARGIN);
    private static final Insets defaultInsets = new Insets(0, 0, 0, 0);

    private JButton saveCurrentButton;
    private JButton saveAllButton;
    private JButton resetButton;

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

    private void createAndShowGui() {
        frame = new JFrame(getClass().getSimpleName());

        monthField = new JTextField(10);
        yearField = new JTextField(10);

        serviceField = new JTextField(10);
        amountField = new JTextField(10);
        counterField = new JTextField(10);
        divisionField = new JTextField(10);

        saveCurrentButton = new JButton("Save Current");
        saveAllButton = new JButton("Save all");
        resetButton = new JButton("Reset");

        buttonsPane = new JPanel();

        topRightPane = new JPanel();
        topRightPane.setLayout(new FlowLayout(FlowLayout.RIGHT));

        topRightPane.add(new JLabel("Month"));
        topRightPane.add(monthField);
        topRightPane.add(new JLabel("Year"));
        topRightPane.add(yearField);

        centerWithButtonPane = new JPanel();
        centerWithButtonPane.setLayout(new BoxLayout(centerWithButtonPane, BoxLayout.PAGE_AXIS));

        Box box = Box.createHorizontalBox();
        box.add(new JLabel("Statement"));
        box.add(Box.createHorizontalGlue());
        box.add(topRightPane);

        centerPane = new JPanel();
        centerPane.setLayout(new GridBagLayout());

        GridBagConstraints gbc = new GridBagConstraints();

        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.insets = defaultInsets;
        centerPane.add(new JLabel("Service"), gbc);

        gbc.gridx = 1;
        gbc.insets = rightInsets;
        centerPane.add(serviceField, gbc);

        gbc.gridx = 2;
        gbc.insets = leftInsets;
        centerPane.add(new JLabel("Counter"), gbc);

        gbc.gridx = 3;
        gbc.insets = defaultInsets;
        centerPane.add(counterField, gbc);

        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.insets = defaultInsets;
        centerPane.add(new JLabel("Amount"), gbc);

        gbc.gridx = 1;
        gbc.insets = rightInsets;
        centerPane.add(amountField, gbc);

        gbc.gridx = 2;
        gbc.insets = leftInsets;
        centerPane.add(new JLabel("Division"), gbc);

        gbc.gridx = 3;
        gbc.insets = defaultInsets;
        centerPane.add(divisionField, gbc);

        saveCurrentButton.setAlignmentX(Component.CENTER_ALIGNMENT); //Force centered alignment for our JButton
        centerWithButtonPane.add(centerPane);
        centerWithButtonPane.add(saveCurrentButton);

        buttonsPane.add(saveAllButton);
        buttonsPane.add(resetButton);

        frame.add(box, BorderLayout.NORTH);
        frame.add(centerWithButtonPane, BorderLayout.CENTER);
        frame.add(buttonsPane, BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

另外请遵循@SergiyMedvynskyy 给出的关于不要混合使用 AWT 和 Swing 组件(即 JTextFieldTextField)的建议,并且只使用 Swing 组件,因为 AWT 组件有问题。