有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

布局不符合Swing中Java的预期

我是一名学生,有一个项目,应该有一个我已经实现的特定布局,除了由于一个错误或由于一些我不知道我做错了的事情而导致的一些间距问题,我已经确定了,所以我很难考虑以不同的方式来处理它。应该是这样的:

Desired Layout

我的应用程序如下所示:

Current Layout

我正在关注Murach的Java编程,并试图仅使用本书范围内的任何东西来解决这个问题

我已经将组件添加到适当的面板中,并将它们添加到带有GridBagLayout的主面板中,以组织所有内容。由于某种原因,文本字段和组合框在单选按钮和复选框添加到面板后挂在右侧。我尝试过创建不同的面板来重新组织、更改布局设置、尝试其他布局、重写整个程序等等。几天前我向教练寻求帮助,但他们还没有回复我。我把Swing的章节读了好几遍,在谷歌上找不到合适的词了

编辑以添加所有代码:

学生调查。爪哇

package student.timothycdykes.studentsurvey;

public class StudentSurvey {

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

}

学生调查框架。爪哇

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 安卓CheckBox = 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(安卓CheckBox);
        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 (安卓CheckBox.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;
    }
}

验证器。爪哇

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;
    }

}

我想补充一点,我知道代码没有遵循最佳实践。这本书中的一些材料已经过时,其中一些正是讲师所要求的


共 (2) 个答案

  1. # 1 楼答案

    It seems the panels containing the check boxes and radio buttons should span 2 columns of the grid bag layout.

    我的怀疑是对的。以下是实施该建议的MRE。我还更改了其中一个文本字段的宽度,以演示不同列大小的效果

    enter image description here

    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);
        }
    }
    
  2. # 2 楼答案

    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.

    你需要理解跨越单元的概念

    网格中的每个单元格都是添加到列中的最大组件的大小

    因此,单选按钮和复选框面板是第一列中最大的组件,因此其他组件显示在这些组件右侧的第二列中

    因此,在为这两个面板创建约束时,需要指定每个面板占用两列的空间

    阅读Swing教程中关于How to Use GridBagLayout的部分,特别是你需要看看gridwidth约束