简体   繁体   English

布局在使用 Java 的 Swing 中没有达到预期的效果

[英]Layout not doing what expected in Swing with Java

I am a student and have a project which is supposed to have a specific layout which I have achieved except for some kind of spacing problem due to a bug or due to something I don't know I'm doing wrong and I've fixated so I'm having trouble thinking about approaching it differently.我是一名学生,有一个项目应该有一个特定的布局,我已经实现了除了由于错误或由于我不知道我做错了什么而我已经固定的某种间距问题所以我很难考虑以不同的方式处理它。 It should look like this:它应该是这样的:

所需布局

My application looks like this:我的应用程序如下所示:

当前布局

I am following along with Murach's Java Programming and trying to solve this problem using anything within the scope of the book only.我正在关注 Murach 的 Java Programming 并尝试仅使用本书范围内的任何内容来解决这个问题。

I have added components to appropriate panels and added those to the main panel with a GridBagLayout to organize everything.我已将组件添加到适当的面板,并使用 GridBagLayout 将它们添加到主面板以组织所有内容。 The text fields and combo box, for some reason, hang to the right after the radio buttons and check boxes are added to the panel.出于某种原因,文本字段和组合框在单选按钮和复选框添加到面板后悬挂在右侧。 I have tried creating different panels to reorganize, changed layout settings, tried other layouts, rewrote the whole program, and more.我尝试创建不同的面板来重新组织、更改布局设置、尝试其他布局、重写整个程序等等。 I asked my instructor for help a few days ago but they haven't gotten back to me yet.几天前我向我的导师寻求帮助,但他们还没有回复我。 I read over the chapters for Swing multiple times and ran out of terms to search for on Google.我多次阅读了 Swing 的章节,但在 Google 上搜索不到任何词条。

Edited to add all of the code:编辑以添加所有代码:

StudentSurvey.java学生调查.java

package student.timothycdykes.studentsurvey;

public class StudentSurvey {

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

}

StudentSurveyFrame.java学生调查框架.java

package student.timothycdykes.studentsurvey;

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

public class StudentSurveyFrame extends JFrame {

    public StudentSurveyFrame(){

        try {
            UIManager.setLookAndFeel(
                UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException | InstantiationException |
                 IllegalAccessException | UnsupportedLookAndFeelException e) {
            System.err.println(e);
        }

        initComponents();
    }

    private void initComponents(){
        setTitle("Student Survey");
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationByPlatform(true);
//        setLayout(new FlowLayout(FlowLayout.LEFT));

        // Text Fields
        Dimension dim = new Dimension(150,20);
        JTextField firstNameTextField = new JTextField();
        JTextField lastNameTextField = new JTextField();
        firstNameTextField.setPreferredSize(dim);
        firstNameTextField.setMinimumSize(dim);
        lastNameTextField.setPreferredSize(dim);
        lastNameTextField.setMinimumSize(dim);

        // Combo Box
        String[] countriesList = {"Select a country...", 
            "Albania", 
            "Bulgaria", 
            "Congo", 
            "Guernsey", 
            "Jamaica", 
            "Korea", 
            "Mozambique", 
            "Oman", 
            "Philippines", 
            "United States", 
            "Other"};
        JComboBox countriesComboBox = new JComboBox(countriesList);

        // Radio Buttons
        ButtonGroup eyeColorButtonGroup = new ButtonGroup();
        JRadioButton brownRadioButton = new JRadioButton("Brown");
        JRadioButton greenRadioButton = new JRadioButton("Green");
        JRadioButton blueRadioButton = new JRadioButton("Blue");
        JRadioButton otherRadioButton = new JRadioButton("Other");
        eyeColorButtonGroup.add(brownRadioButton);
        eyeColorButtonGroup.add(greenRadioButton);
        eyeColorButtonGroup.add(blueRadioButton);
        eyeColorButtonGroup.add(otherRadioButton);
        JPanel radioButtonPanel = new JPanel();
        //radioButtonPanel.setBorder(BorderFactory.createEmptyBorder());
        radioButtonPanel.add(brownRadioButton);
        radioButtonPanel.add(greenRadioButton);
        radioButtonPanel.add(blueRadioButton);
        radioButtonPanel.add(otherRadioButton);

        // Check Boxes
        JCheckBox HTMLCheckBox = new JCheckBox("HTML");
        JCheckBox SQLCheckBox = new JCheckBox("SQL");
        JCheckBox javaCheckBox = new JCheckBox("Java");
        JCheckBox androidCheckBox = new JCheckBox("Android");
        JCheckBox pythonCheckBox = new JCheckBox("Python");
        JPanel checkBoxPanel = new JPanel();
        //checkBoxPanel.setBorder(BorderFactory.createEmptyBorder());
        checkBoxPanel.add(HTMLCheckBox);
        checkBoxPanel.add(SQLCheckBox);
        checkBoxPanel.add(javaCheckBox);
        checkBoxPanel.add(androidCheckBox);
        checkBoxPanel.add(pythonCheckBox);

        // Buttons
        JButton submitButton = new JButton("Submit");
        submitButton.addActionListener(e -> {

            // Create a message to append data to
            String message = "Thanks for taking our survey!\n\n"
                    + "Here's the data you entered:\n";


            // Get the name
            String firstName = firstNameTextField.getText();
            String lastName = lastNameTextField.getText();

            // Get the country
            int countryIndex = countriesComboBox.getSelectedIndex();
            String country = countriesList[countryIndex];

            // Get the eye color
            String eyeColor = "";
            if (brownRadioButton.isSelected()) {
                eyeColor = "Brown";
            } else if (greenRadioButton.isSelected()) {
                eyeColor = "Green";
            } else if (blueRadioButton.isSelected()) {
                eyeColor = "Blue";
            } else if (otherRadioButton.isSelected()) {
                eyeColor = "Other";
            }

            // Get the skills
            String skills = "";
            if (HTMLCheckBox.isSelected()) {
                skills += "HTML";
            }
            if (SQLCheckBox.isSelected()) {
                skills += ", SQL";
            }
            if (javaCheckBox.isSelected()) {
                skills += ", Java";
            }
            if (androidCheckBox.isSelected()) {
                skills += ", Android";
            }
            if (pythonCheckBox.isSelected()) {
                skills += ", Python";
            }

            // Validate, append to message, and show a dialog box
            if (Validator.isEmpty(firstName, "First name") && Validator.isEmpty(lastName, "Last name")
                    && Validator.isZeroIndex(countryIndex, "Country") && Validator.isEmpty(eyeColor, "Eye color")) {
                message += "Name: " + firstName + " " + lastName + "\n";
                message += "Country: " + country + "\n";
                message += "Eye color: " + eyeColor + "\n";
                message += "Skills: " + skills;
                JOptionPane.showMessageDialog(this, message, "Message", JOptionPane.INFORMATION_MESSAGE);
            }

        });
        JButton exitButton = new JButton("Exit");
        exitButton.addActionListener(e -> {
           System.exit(0); 
        });
        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
        buttonPanel.add(submitButton);
        buttonPanel.add(exitButton);

        // Grid Panel
        JPanel northGridPanel = new JPanel();
        northGridPanel.setLayout(new GridBagLayout());
        northGridPanel.add(new JLabel("First Name:"), getConstraints(0,0));
        northGridPanel.add(firstNameTextField, getConstraints(1,0));
        northGridPanel.add(new JLabel("Last Name:"), getConstraints(0,1));
        northGridPanel.add(lastNameTextField, getConstraints(1,1));
        northGridPanel.add(new JLabel("Country:"), getConstraints(0,2));
        northGridPanel.add(countriesComboBox, getConstraints(1,2));
        northGridPanel.add(new JLabel("Eye color:"), getConstraints(0,3));
        northGridPanel.add(radioButtonPanel, getConstraints(0,4));
        northGridPanel.add(new JLabel("Programming skills:"), getConstraints(0,5));
        northGridPanel.add(checkBoxPanel, getConstraints(0,6));

        // Construct the frame
        add(northGridPanel, BorderLayout.CENTER);
        add(buttonPanel, BorderLayout.SOUTH);
        pack();
        setVisible(true);
        setLocationRelativeTo(null);
    }

    private GridBagConstraints getConstraints(int x, int y) {
        GridBagConstraints c = new GridBagConstraints();
        c.anchor = GridBagConstraints.LINE_START;
        c.insets = new Insets(5, 5, 0, 5);
        c.gridx = x;
        c.gridy = y;
        return c;
    }
}

Validator.java验证器.java

package student.timothycdykes.studentsurvey;

import javax.swing.JOptionPane;

public class Validator {

    private static void generateErrorDialog(String field) {
        String message = "";
        message += field + " is a required field."
                + "\nPlease complete this field before submitting.";
        JOptionPane.showMessageDialog(null, message, "Error", JOptionPane.ERROR_MESSAGE);
    }

    public static boolean isEmpty(String string, String field) {
        boolean isValid = true;
        if (string.equals("")) {
            isValid = false;
            generateErrorDialog(field);
        }
        return isValid;
    }

    public static boolean isZeroIndex(int index, String field) {
        boolean isValid = true;
        if(index == 0) {
            isValid = false;
            generateErrorDialog(field);
        }
        return isValid;
    }

}

I would like to add that I know the code is not following best practices.我想补充一点,我知道代码没有遵循最佳实践。 Some of the material in this book is outdated and some of it is just how the instructor requires things to be.本书中的一些材料已经过时,而其中一些材料正是教师所要求的。

It seems the panels containing the check boxes and radio buttons should span 2 columns of the grid bag layout.似乎包含复选框和单选按钮的面板应该跨越网格包布局的2

My suspicion was correct.我的怀疑是正确的。 Herein is an MRE implementing the suggestion.这是一个实施该建议的 MRE。 I also changed the width of one of the text fields in order to demonstrate the effect of different column sizes.我还更改了其中一个文本字段的宽度,以演示不同列大小的效果。

在此处输入图片说明

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

/* Do NOT extend components, containers or windows without good cause. It is
 done here in order to stick to the spirit of the code in the question. */
public class LayoutProblemGBL extends JFrame {

    LayoutProblemGBL() {
        initComponents();
    }

    private void initComponents() {
        setTitle("Student Survey");
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationByPlatform(true);

        // Text Fields
        //Dimension dim = new Dimension(150, 20);
        JTextField firstNameTextField = new JTextField(20);
        JTextField lastNameTextField = new JTextField(18);

        // Combo Box
        String[] countriesList = {"Select a country...",
            "Albania",
            "United States"};
        JComboBox countriesComboBox = new JComboBox(countriesList);

        // Radio Buttons
        JRadioButton brownRadioButton = new JRadioButton("Brown");
        JRadioButton greenRadioButton = new JRadioButton("Green");
        JRadioButton blueRadioButton = new JRadioButton("Blue");
        JRadioButton otherRadioButton = new JRadioButton("Other");
        JPanel radioButtonPanel = new JPanel();
        radioButtonPanel.add(brownRadioButton);
        radioButtonPanel.add(greenRadioButton);
        radioButtonPanel.add(blueRadioButton);
        radioButtonPanel.add(otherRadioButton);

        // Check Boxes
        JCheckBox HTMLCheckBox = new JCheckBox("HTML");
        JCheckBox SQLCheckBox = new JCheckBox("SQL");
        JCheckBox javaCheckBox = new JCheckBox("Java");
        JCheckBox androidCheckBox = new JCheckBox("Android");
        JCheckBox pythonCheckBox = new JCheckBox("Python");
        JPanel checkBoxPanel = new JPanel();
        checkBoxPanel.add(HTMLCheckBox);
        checkBoxPanel.add(SQLCheckBox);
        checkBoxPanel.add(javaCheckBox);
        checkBoxPanel.add(androidCheckBox);
        checkBoxPanel.add(pythonCheckBox);

        // Buttons
        JButton submitButton = new JButton("Submit");
        JButton exitButton = new JButton("Exit");
        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
        buttonPanel.add(submitButton);
        buttonPanel.add(exitButton);

        // Grid Panel
        JPanel northGridPanel = new JPanel();
        northGridPanel.setLayout(new GridBagLayout());
        northGridPanel.add(new JLabel("First Name:"), getConstraints(0, 0));
        northGridPanel.add(firstNameTextField, getConstraints(1, 0));
        northGridPanel.add(new JLabel("Last Name:"), getConstraints(0, 1));
        northGridPanel.add(lastNameTextField, getConstraints(1, 1));
        northGridPanel.add(new JLabel("Country:"), getConstraints(0, 2));
        northGridPanel.add(countriesComboBox, getConstraints(1, 2));
        northGridPanel.add(new JLabel("Eye color:"), getConstraints(0, 3));
        northGridPanel.add(radioButtonPanel, getConstraints(0, 4, 2));
        northGridPanel.add(new JLabel("Programming skills:"), getConstraints(0, 5));
        northGridPanel.add(checkBoxPanel, getConstraints(0, 6, 2));

        // Construct the frame
        add(northGridPanel, BorderLayout.CENTER);
        add(buttonPanel, BorderLayout.SOUTH);
        pack();
        setVisible(true);
        setLocationRelativeTo(null);
    }

    private GridBagConstraints getConstraints(int x, int y) {
        return getConstraints(x, y, 1);
    }

    private GridBagConstraints getConstraints(int x, int y, int width) {
        GridBagConstraints c = new GridBagConstraints();
        c.anchor = GridBagConstraints.LINE_START;
        c.insets = new Insets(5, 5, 0, 5);
        c.gridx = x;
        c.gridy = y;
        c.gridwidth = width;
        return c;
    }

    public static void main(String[] args) {
        Runnable r = () -> {
            new LayoutProblemGBL();
        };
        SwingUtilities.invokeLater(r);
    }
}

The text fields and combo box, for some reason, hang to the right after the radio buttons and check boxes are added to the panel.出于某种原因,文本字段和组合框在单选按钮和复选框添加到面板后悬挂在右侧。

You need to understand the concept of spanning cells.您需要了解跨越单元格的概念。

Each cell in the grid will be the size of the largest component added to the column.网格中的每个单元格将是添加到列中的最大组件的大小。

So your radio buttons and check box panels are the largest components in the first column, so the other components are displayed in the second column to the right of those components.因此,您的单选按钮和复选框面板是第一列中最大的组件,因此其他组件显示在这些组件右侧的第二列中。

So, when you create your constraints for those two panels you need to specify that each panel takes up the space of two columns.因此,当您为这两个面板创建约束时,您需要指定每个面板占用两列的空间。

Read the section from the Swing tutorial on How to Use GridBagLayout , specifically you need to look at the gridwidth constraint`.阅读 Swing 教程中关于如何使用 GridBagLayout 的部分,特别是您需要查看gridwidth约束gridwidth

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM