如何在 window 中定义一条中间线并将所有元素对齐到这条线

How to define a middle line in a window and align all elements to this line

标题问题可能措辞不当,但我可以给你看一张图,你就会明白我的意思:

如您所见,顶部和底部面板的布局应独立于居中。

我试图通过 BoxLayout 实现主要 PanelGridBagLayout 实现,单个 PanelJSeparator 分隔。但我对此有一些困难。我不会抱怨这些困难,但我只是想得到一些帮助来制作这个(简单的)布局。

这是我当前状态的 SSCCE:

public class GridBagLayoutProblem extends JFrame
{

    private final JTextArea generatorTextArea;
    private JTextArea message1TextArea;
    private JTextArea message2TextArea;
    private JButton loadButton;
    private JButton browseButton;
    private JButton saveButton;
    private JTextField solution1TextField;
    private JTextField solution2TextField;
    private JCheckBox questionCheckBox;
    private JTextField locationTextField;
    public GridBagLayoutProblem()
    {
        super("GridBagLayout Problem SSCCE");

        // Build GUI
        setLocationRelativeTo(null);
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

        // Prepare Layouts
        final BoxLayout bLayout = new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS);

        final Insets horizInsets = new Insets(0, 5, 0, 5);
        final Insets horizVertInsets = new Insets(5, 5, 5, 5);
        final Insets generatorTextAreaInsets = new Insets(5, 5, 5, 24);
        final Insets message1TextAreaInsets = new Insets(5, 5, 5, 64);
        final Insets message2TextAreaInsets = new Insets(5, 5, 5, 64);
        final Insets buttonMarginInsets = new Insets(-1, 0, -2, 0);

        setLayout(bLayout);

        // Exercise loading panel
        final JPanel eLoadPanel = new JPanel();
        final GridBagLayout gbLayout_eLoadPanel = new GridBagLayout();
        eLoadPanel.setLayout(gbLayout_eLoadPanel);

        final JTextField matNrTextField = new JTextField();
        final GridBagConstraints gbc_matNrTextField = new GridBagConstraints();
        gbc_matNrTextField.fill = GridBagConstraints.HORIZONTAL;
        gbc_matNrTextField.gridx = 0;
        gbc_matNrTextField.gridy = 0;
        gbc_matNrTextField.weightx = 1;
        gbc_matNrTextField.insets = new Insets(0, 210, 0, 0);
        eLoadPanel.add(matNrTextField, gbc_matNrTextField);

        loadButton = new JButton("Load/Unload");
        final GridBagConstraints gbc_loadButton = new GridBagConstraints();
        gbc_loadButton.fill = GridBagConstraints.NONE;
        gbc_loadButton.gridx = 1;
        gbc_loadButton.gridy = 0;
        gbc_loadButton.weightx = 0;
        gbc_loadButton.weighty = 0;
        gbc_loadButton.insets = horizVertInsets;
        loadButton.setMargin(buttonMarginInsets);
        eLoadPanel.add(loadButton, gbc_loadButton);

        add(eLoadPanel);

        add(new JSeparator(SwingConstants.HORIZONTAL));

        // Generator Polynom Panel
        final JPanel generatorPanel = new JPanel();
        final GridBagLayout gbLayout_generatorPanel = new GridBagLayout();
        generatorPanel.setLayout(gbLayout_generatorPanel);

        final JLabel generatorLabel = new JLabel("Generatorpolynom: ", SwingConstants.RIGHT);
        final GridBagConstraints gbc_generatorLabel = new GridBagConstraints();
        gbc_generatorLabel.fill = GridBagConstraints.HORIZONTAL;
        gbc_generatorLabel.gridx = 0;
        gbc_generatorLabel.gridy = 0;
        gbc_generatorLabel.weightx = 0;
        gbc_generatorLabel.insets = horizVertInsets;
        generatorPanel.add(generatorLabel, gbc_generatorLabel);

        generatorTextArea = new JTextArea();
        generatorTextArea.setEditable(false);
        generatorTextArea.setFocusable(false);
        final GridBagConstraints gbc_generatorTextArea = new GridBagConstraints();
        gbc_generatorTextArea.fill = GridBagConstraints.HORIZONTAL;
        gbc_generatorTextArea.gridx = 1;
        gbc_generatorTextArea.gridy = 0;
        gbc_generatorTextArea.weightx = 0;
        gbc_generatorTextArea.insets = generatorTextAreaInsets;
        generatorPanel.add(generatorTextArea, gbc_generatorTextArea);

        add(generatorPanel);

        add(new JSeparator(SwingConstants.HORIZONTAL));

        // Task1 Panel - Calculate transferred message
        final JPanel task1Panel = new JPanel();
        final GridBagLayout gbLayout_task1Panel = new GridBagLayout();
        task1Panel.setLayout(gbLayout_task1Panel);

        final JLabel message1Label = new JLabel("Die zu übertragende Nachricht: ", SwingConstants.RIGHT);
        final GridBagConstraints gbc_message1Label = new GridBagConstraints();
        gbc_message1Label.fill = GridBagConstraints.HORIZONTAL;
        gbc_message1Label.gridx = 0;
        gbc_message1Label.gridy = 0;
        gbc_message1Label.weightx = 0;
        gbc_message1Label.insets = horizVertInsets;
        task1Panel.add(message1Label, gbc_message1Label);

        message1TextArea = new JTextArea();
        message1TextArea.setEditable(false);
        message1TextArea.setFocusable(false);
        final GridBagConstraints gbc_message1TextArea = new GridBagConstraints();
        gbc_message1TextArea.fill = GridBagConstraints.HORIZONTAL;
        gbc_message1TextArea.gridx = 1;
        gbc_message1TextArea.gridy = 0;
        gbc_message1TextArea.weightx = 0;
        gbc_message1TextArea.insets = message1TextAreaInsets;
        task1Panel.add(message1TextArea, gbc_message1TextArea);

        final JLabel solution1Label = new JLabel("Übertragene Nachricht inkl. redundante Bits: ", SwingConstants.RIGHT);
        final GridBagConstraints gbc_solution1Label = new GridBagConstraints();
        gbc_solution1Label.fill = GridBagConstraints.HORIZONTAL;
        gbc_solution1Label.gridx = 0;
        gbc_solution1Label.gridy = 1;
        gbc_solution1Label.weightx = 0;
        gbc_solution1Label.insets = horizVertInsets;
        task1Panel.add(solution1Label, gbc_solution1Label);

        solution1TextField = new JTextField();
        final GridBagConstraints gbc_solution1TextField = new GridBagConstraints();
        gbc_solution1TextField.fill = GridBagConstraints.HORIZONTAL;
        gbc_solution1TextField.gridx = 1;
        gbc_solution1TextField.gridy = 1;
        gbc_solution1TextField.insets = message1TextAreaInsets;
        gbc_solution1TextField.weightx = 1; // important
        task1Panel.add(solution1TextField, gbc_solution1TextField);

        add(task1Panel);

        add(new JSeparator(SwingConstants.HORIZONTAL));

        // Task 2 Panel -
        final JPanel task2Panel = new JPanel();
        final GridBagLayout gbLayout_task2Panel = new GridBagLayout();
        task2Panel.setLayout(gbLayout_task2Panel);

        final JLabel message2Label = new JLabel("Die empfangene Nachricht: ", SwingConstants.RIGHT);
        final GridBagConstraints gbc_message2Label = new GridBagConstraints();
        gbc_message2Label.fill = GridBagConstraints.HORIZONTAL;
        gbc_message2Label.gridx = 0;
        gbc_message2Label.gridy = 0;
        gbc_message2Label.weightx = 0;
        gbc_message2Label.insets = horizVertInsets;
        task2Panel.add(message2Label, gbc_message2Label);

        message2TextArea = new JTextArea();
        message2TextArea.setEditable(false);
        message2TextArea.setFocusable(false);
        final GridBagConstraints gbc_message2TextArea = new GridBagConstraints();
        gbc_message2TextArea.fill = GridBagConstraints.HORIZONTAL;
        gbc_message2TextArea.gridx = 1;
        gbc_message2TextArea.gridy = 0;
        gbc_message2TextArea.weightx = 0;
        gbc_message2TextArea.insets = message2TextAreaInsets;
        task2Panel.add(message2TextArea, gbc_message2TextArea);

        final JLabel solution2Label = new JLabel("Divisionsrest: ", SwingConstants.RIGHT);
        final GridBagConstraints gbc_solution2Label = new GridBagConstraints();
        gbc_solution2Label.fill = GridBagConstraints.HORIZONTAL;
        gbc_solution2Label.gridx = 0;
        gbc_solution2Label.gridy = 1;
        gbc_solution2Label.weightx = 0;
        gbc_solution2Label.insets = horizVertInsets;
        task2Panel.add(solution2Label, gbc_solution2Label);

        solution2TextField = new JTextField();
        final GridBagConstraints gbc_solution2TextField = new GridBagConstraints();
        gbc_solution2TextField.fill = GridBagConstraints.HORIZONTAL;
        gbc_solution2TextField.gridx = 1;
        gbc_solution2TextField.gridy = 1;
        gbc_solution2TextField.insets = message2TextAreaInsets;
        gbc_solution2TextField.weightx = 1; // important
        task2Panel.add(solution2TextField, gbc_solution2TextField);

        final JLabel questionLabel = new JLabel("Ist das übertragene Polynom fehlerbehaftet?");
        final GridBagConstraints gbc_questionLabel = new GridBagConstraints();
        gbc_questionLabel.fill = GridBagConstraints.HORIZONTAL;
        gbc_questionLabel.gridx = 0;
        gbc_questionLabel.gridy = 2;
        gbc_questionLabel.weightx = 1;
        gbc_questionLabel.insets = horizInsets;
        task2Panel.add(questionLabel, gbc_questionLabel);

        questionCheckBox = new JCheckBox();
        questionCheckBox.setEnabled(false);
        final GridBagConstraints gbc_questionCheckBox = new GridBagConstraints();
        gbc_questionCheckBox.gridx = 1;
        gbc_questionCheckBox.gridy = 2;
        gbc_questionCheckBox.weightx = 0;
        task2Panel.add(questionCheckBox, gbc_questionCheckBox);

        add(task2Panel);

        add(new JSeparator(SwingConstants.HORIZONTAL));

        // Save Panel
        final JPanel savePanel = new JPanel();
        final GridBagLayout gbLayout_savePanel = new GridBagLayout();
        savePanel.setLayout(gbLayout_savePanel);

        locationTextField = new JTextField(System.getProperty("user.dir"));
        final GridBagConstraints gbc_locationTextField = new GridBagConstraints();
        gbc_locationTextField.fill = GridBagConstraints.HORIZONTAL;
        gbc_locationTextField.gridx = 0;
        gbc_locationTextField.gridy = 0;
        gbc_locationTextField.weightx = 1;
        gbc_locationTextField.insets = horizVertInsets;
        savePanel.add(locationTextField, gbc_locationTextField);

        browseButton = new JButton("Durchsuchen...");
        browseButton.setEnabled(false);
        final GridBagConstraints gbc_browseButton = new GridBagConstraints();
        gbc_browseButton.gridx = 1;
        gbc_browseButton.gridy = 0;
        gbc_browseButton.weightx = 0;
        browseButton.setMargin(buttonMarginInsets);
        savePanel.add(browseButton, gbc_browseButton);

        saveButton = new JButton("Speichern");
        saveButton.setEnabled(false);
        final GridBagConstraints gbc_saveButton = new GridBagConstraints();
        gbc_saveButton.gridx = 2;
        gbc_saveButton.gridy = 0;
        gbc_saveButton.weightx = 0;
        saveButton.setMargin(buttonMarginInsets);
        savePanel.add(saveButton, gbc_saveButton);

        add(savePanel);

        setResizable(false);
        setSize(450, 287);
        setVisible(true);

        // add listeners
        loadButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                if (browseButton.isEnabled())
                    unload();
                else
                    load();
            }
        });

        browseButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(final ActionEvent e)
            {
                final File path = new File(locationTextField.getText());
                final JFileChooser fileChooser = new JFileChooser();
                fileChooser.setCurrentDirectory(path);
                fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                if (fileChooser.showOpenDialog(getParent()) == JFileChooser.APPROVE_OPTION)
                {
                    locationTextField.setText(fileChooser.getSelectedFile().getAbsolutePath());
                }
            }
        });

    }

    private void load()
    {
        generatorTextArea.setText("10111");
        message1TextArea.setText("10101111");
        message2TextArea.setText("10010010110");
        browseButton.setEnabled(true);
        saveButton.setEnabled(true);
        questionCheckBox.setEnabled(true);
        getRootPane().setDefaultButton(saveButton);
        solution1TextField.requestFocus();
    }


    private void unload()
    {
        browseButton.setEnabled(false);
        saveButton.setEnabled(false);
        getRootPane().setDefaultButton(loadButton);
        message1TextArea.setText("");
        generatorTextArea.setText("");
        questionCheckBox.setEnabled(false);
    }

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

使用 GridBagLayoutGridBagLayout 允许您定义单元格来定位组件。

因此,在您的示例中,您基本上会有两列和多行。阅读有关 How to Use GridBagLayout 的 Swing 教程部分,了解更多信息和示例。

对于JSeparator,您可以指定组件占用2列的宽度。对于最后一行,您需要为两个按钮创建一个单独的面板,然后使用 GridBagLayout.

将面板添加到主面板上的单元格中

重点是您可以使用具有不同布局管理器的嵌套面板来实现您想要的布局。

As you see the layout of top and bottom panels should be independent from the centering.

我在回答中解决了这个问题。您创建一个面板,可能使用简单的 FlowLayout(右对齐或左对齐),将组件添加到面板并让面板跨越多列。

正如您可能从我的示例中看到的那样 - 我的布局几乎达到了我可以满意的程度。现在我终于完成了UI。在我问这个问题之前我遗漏的关键点是 关于嵌套面板。我在我的代码中考虑了嵌套面板的使用,结果我使用了太多的面板!所以我扔掉了三个应该有公共中间点(generatorPaneltask1Paneltask2Panel)的单面板,并用一个我称为 midPanel 的面板替换了它们其余的(设置约束等)从这一点开始很容易。