[英]Layout not doing what expected in Swing with Java
我是一名學生,有一個項目應該有一個特定的布局,我已經實現了除了由於錯誤或由於我不知道我做錯了什么而我已經固定的某種間距問題所以我很難考慮以不同的方式處理它。 它應該是這樣的:
我的應用程序如下所示:
我正在關注 Murach 的 Java Programming 並嘗試僅使用本書范圍內的任何內容來解決這個問題。
我已將組件添加到適當的面板,並使用 GridBagLayout 將它們添加到主面板以組織所有內容。 出於某種原因,文本字段和組合框在單選按鈕和復選框添加到面板后懸掛在右側。 我嘗試創建不同的面板來重新組織、更改布局設置、嘗試其他布局、重寫整個程序等等。 幾天前我向我的導師尋求幫助,但他們還沒有回復我。 我多次閱讀了 Swing 的章節,但在 Google 上搜索不到任何詞條。
編輯以添加所有代碼:
學生調查.java
package student.timothycdykes.studentsurvey;
public class StudentSurvey {
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(() -> {
new 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;
}
}
驗證器.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列。
我的懷疑是正確的。 這是一個實施該建議的 MRE。 我還更改了其中一個文本字段的寬度,以演示不同列大小的效果。
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);
}
}
出於某種原因,文本字段和組合框在單選按鈕和復選框添加到面板后懸掛在右側。
您需要了解跨越單元格的概念。
網格中的每個單元格將是添加到列中的最大組件的大小。
因此,您的單選按鈕和復選框面板是第一列中最大的組件,因此其他組件顯示在這些組件右側的第二列中。
因此,當您為這兩個面板創建約束時,您需要指定每個面板占用兩列的空間。
閱讀 Swing 教程中關於如何使用 GridBagLayout 的部分,特別是您需要查看gridwidth
約束gridwidth
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.