单击确定按钮后如何获取输入?

How can I get the inputs after the OK button is clicked?

我是Java的新手,遇到了一个很烦人的情况,三天了都弄不明白。我先 post 我的代码。

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;

public class StudentInfo extends JFrame {

ArrayList<Student> lstStudent = new ArrayList<Student>();

private JTable table = null;
private JButton btnAdd = null;

public StudentInfo() {
    table = new JTable();
    btnAdd = new JButton("Add");
    this.getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
    this.getContentPane().add(btnAdd, BorderLayout.SOUTH);
    this.setSize(600, 400);
    this.setVisible(true);
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);

    updateTable();

    btnAdd.addActionListener(event -> {
        addStudent();
    });
}

public void addStudent() {
    StudentDetailDialog dialog = new StudentDetailDialog();
    Student student = new Student();
    student = dialog.dialog2Student();
    updateTable();
}

public void updateTable() {
    if(lstStudent.size() > 0) {
        Vector<Vector<Object>> tableData = new Vector<>();
        for(Student tempStudent : lstStudent) {
            Vector<Object> rowData = new Vector<>();
            rowData.add(tempStudent.getGiven());
            rowData.add(tempStudent.getLast());
            rowData.add(tempStudent.getGender());
            rowData.add(tempStudent.getAge());
            tableData.add(rowData);
        }

        Vector<String> colLabel = new Vector<>();
        colLabel.addAll(Arrays.<String> asList("Given Name", "Last Name", "Gender", "Age"));
        table.setModel(new DefaultTableModel(tableData, colLabel));
    }
    else {
        table.setModel(new DefaultTableModel(new Vector<>(), new Vector<>()));
    }
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(() -> {
        new StudentInfo();
    });
}
}

class StudentDetailDialog extends JDialog {

private JLabel lblGiven = null;
private JTextField txtGiven = null;
private JLabel lblLast = null;
private JTextField txtLast = null;
private JLabel lblGender = null;
private JTextField txtGender = null;
private JLabel lblAge = null;
private JTextField txtAge = null;

private JButton btnOK = null;
private JButton btnCancel = null;

public StudentDetailDialog() {
    JPanel pnlCenter = new JPanel(new GridLayout(4, 2));
    lblGiven = new JLabel("Given Name:");
    txtGiven = new JTextField(10);
    lblLast = new JLabel("Last Name:");
    txtLast = new JTextField(10);
    lblGender = new JLabel("Gender:");
    txtGender = new JTextField(10);
    lblAge = new JLabel("Age:");
    txtAge = new JTextField(10);
    pnlCenter.add(lblGiven);
    pnlCenter.add(txtGiven);
    pnlCenter.add(lblLast);
    pnlCenter.add(txtLast);
    pnlCenter.add(lblGender);
    pnlCenter.add(txtGender);
    pnlCenter.add(lblAge);
    pnlCenter.add(txtAge);

    JPanel pnlSouth = new JPanel();
    btnOK = new JButton("OK");
    btnCancel = new JButton("Cancel");
    pnlSouth.add(btnOK);
    pnlSouth.add(btnCancel);

    this.add(pnlCenter, BorderLayout.CENTER);
    this.add(pnlSouth, BorderLayout.SOUTH);
    this.setSize(250, 200);
    this.setVisible(true);
    this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);

    btnOK.addActionListener(event -> {
        dispose();
    });

    btnCancel.addActionListener(event -> {
        dispose();
    });
}

public Student dialog2Student() {
    Student student = new Student();
    student.setGiven(txtGiven.getText());
    student.setLast(txtLast.getText());
    student.setGender(txtGender.getText());
    student.setAge(Integer.valueOf(txtAge.getText()));
    return student;
}
}

class Student {
private String givenName = null;
private String lastName = null;
private String gender = null;
private int age = 0;

public void setGiven(String givenName) {
    this.givenName = givenName;
}

public String getGiven() {
    return givenName;
}

public void setLast(String lastName) {
    this.lastName = lastName;
}

public String getLast() {
    return lastName;
}

public void setGender(String gender) {
    this.gender = gender;
}

public String getGender() {
    return gender;
}

public void setAge(int age) {
    this.age = age;
}

public int getAge() {
    return age;
}
}

我想做的是创建一个 table 并向其中添加一些学生。但是点击 "add" 按钮后,立即出现错误,我什至没有时间输入单词。我该怎么做才能弄清楚?错误消息附在下面。

Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.valueOf(Unknown Source)
at class_demo.StudentDetailDialog.dialog2Student(StudentInfo.java:137)
at class_demo.StudentInfo.addStudent(StudentInfo.java:46)
at class_demo.StudentInfo.lambda[=11=](StudentInfo.java:39)
at class_demo.StudentInfo$$Lambda/32103433.actionPerformed(Unknown Source)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access0(Unknown Source)
at java.awt.EventQueue.run(Unknown Source)
at java.awt.EventQueue.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.run(Unknown Source)
at java.awt.EventQueue.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

希望你们都明白我在说什么,因为我不是母语人士。无论如何,谢谢你们!

A JDialog 在输入所有详细信息之前不会停止执行流程。

作为一种简单的解决方法,您可能希望将 StudentDetailDialog 设为 JPanel,然后将其环绕在 JOptionPane.

周围
public void addStudent() {
    StudentDetailDialog dialog = new StudentDetailDialog();
    int result = JOptionPane.showConfirmDialog(null, dialog, "Student Details", JOptionPane.OK_CANCEL_OPTION);
    if (result == JOptionPane.OK_OPTION) {
        Student student = dialog.dialog2Student();
        updateTable();
    }
}

然后将 StudentDetailDialog 更改为 JPanel

class StudentDetailDialog extends JPanel {
    // Remove the Add and Cancel buttons since it would be part of JOptionPane.
}

正如我在评论中指出的那样,您的异常消息准确地告诉您出了什么问题——您正在尝试将一个空字符串 "" 解析为一个数字,以及它出现的行:student.setAge(Integer.valueOf(txtAge.getText()));

问题包括

  • 您的 JDialog 是非模态的,因此您从对话框中提取数据的代码在用户有机会与对话框交互之前被调用。
  • 通过在 JDialog 构造函数(使用 ModalityType 参数的构造函数)中调用适当的超级构造函数使对话框成为模态来解决此问题。
  • 不要将对话框设置为在构造函数中可见,因为这会冻结 setVisible(true) 调用下方的所有构造函数代码,使您的程序无用。
  • 而是让调用代码调用集在对话框中可见完全构建之后。
  • 您的对话框的 btnOK 和 btnCancel ActionListeners 是相同的,因此您的程序无法知道用户按下了哪个按钮。您可以通过为对话框提供某种类型的状态变量并在调用 dispose 之前在这些 ActionListeners 中设置它来解决此问题。