Макет не делает то, что ожидалось в Swing с Java - PullRequest
2 голосов
/ 07 марта 2020

Я студент и у меня есть проект, который должен иметь заданный макет c, которого я достиг, за исключением некоторой проблемы с пробелами из-за ошибки или из-за того, что я не знаю, что делаю неправильно, и я зациклился, поэтому у меня возникают проблемы с подходом к нему по-другому. Это должно выглядеть так:

Desired Layout

Мое приложение выглядит так:

Current Layout

Я следую вместе с Java Murach's Programming и пытаюсь решить эту проблему, используя что-либо только в рамках книги.

Я добавил компоненты на соответствующие панели и добавил их на главную панель с GridBagLayout, чтобы организовать все. Текстовые поля и поле со списком, по некоторым причинам, висят справа после того, как переключатели и флажки добавлены на панель. Я попытался создать различные панели для реорганизации, изменил настройки макета, пробовал другие макеты, переписал всю программу и многое другое. Я попросил моего инструктора о помощи несколько дней go, но они до сих пор мне не ответили. Я перечитал главы о Swing несколько раз, и у меня закончились условия поиска в Google.

Отредактировано, чтобы добавить весь код:

StudentSurvey. java

package student.timothycdykes.studentsurvey;

public class StudentSurvey {

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

}

StudentSurveyFrame. 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

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 ]

2 голосов
/ 07 марта 2020

Кажется, что панели, содержащие флажки и переключатели, должны охватывать 2 столбцов макета мешка сетки.

Мое подозрение было верным. Здесь 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);
    }
}
1 голос
/ 07 марта 2020

Текстовые поля и поле со списком по какой-то причине зависают справа после того, как переключатели и флажки добавлены на панель.

Вам необходимо понять концепцию охватывающих ячеек.

Каждая ячейка в сетке будет иметь размер самого большого компонента, добавляемого в столбец.

Итак Ваши переключатели и панели-флажки являются самыми большими компонентами в первом столбце, поэтому остальные компоненты отображаются во втором столбце справа от этих компонентов.

Итак, когда вы создаете свои ограничения для этих двух панелей вам нужно указать, что каждая панель занимает пространство двух столбцов.

Прочтите раздел из учебника по Swing на Как использовать GridBagLayout , особенно вам нужно взглянуть на gridwidth constraint`.

...