将 JTable 中的 phone 数字列格式化为“(area) prefix-number”

Format phone number column in JTable as "(area) prefix-number"

我目前正在使用 JDBC 存储客户输入数据库的 phone 号码,然后将 phone 号码显示在 JTable 中。我可以在不使用 TableCellRenderer 的情况下使其工作,但我希望该数字在 table 中显示为(区域)前缀数字格式。这是我用来尝试实现此目的的代码:

    //core package
    public class Patient {

        private int id;
        private String firstName;
        private String middleName;
        private String lastName;
        private String phneNum;
        private String email;

    public Patient(String firstName, String middleName, String lastName, String phneNum, String email) {
        this(0, firstName, middleName, lastName, phneNum, email);
    }

    public Patient(int id, String firstName, String middleName, String lastName, String phneNum, String email) {
        super();
        this.id = id;
        this.firstName = firstName;
        this.middleName = middleName;
        this.lastName = lastName;
        this.phneNum = phneNum;
        this.email = email;
    }

    public int getId() {
        return id;
    }
    public void setId() {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }
    public void setFirstName() {
        this.firstName = firstName;
    }

    public String getMiddleName() {
        return middleName;
    }
    public void setMiddleName() {
        this.middleName = middleName;
    }

    public String getLastName() {
        return lastName;
    }
    public void setLastName() {
        this.lastName = lastName;
    }

    public String getPhneNum() {
        return phneNum;
    }
    public void setPhneNum() {
        this.phneNum = phneNum;
    }

    public String getEmail() {
        return email;
    }
    public void setEmail() {
        this.email = email;
    }

    @Override
    public String toString() {
        return String.format("Patient [id=%s, firstName=%s, middleName=%s, lastName=%s, phneNum=%s, email=%s", 
                id, firstName, middleName, lastName, phneNum, email);
    }

}

public class PhoneNumber {
    public String areaCode;
    public String prefix;
    public String num;

    private PhoneNumber() {}

    public PhoneNumber(String areaCode, String prefix, String num) {
        this.areaCode = areaCode;
        this.prefix = prefix;
        this.num = num;
    }

    @Override
    public String toString() {
        return "areaCode=" + areaCode + "; prefix=" + prefix + "; num=" + num;
    }
}

//DAO Package
import java.io.FileInputStream;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import com.patientsessiontracker.core.*;

public class PatientDAO {

    private Connection dbConn;

    public PatientDAO() throws Exception {

        // get db properties
        Properties config = new Properties();
        config.load(new FileInputStream("Patient Session Tracker Config/patientSessionTracker.properties"));

        String user = config.getProperty("user");
        String password = config.getProperty("password");
        String dburl = config.getProperty("dburl");

        // connect to database
        dbConn = DriverManager.getConnection(dburl, user, password);

        System.out.println("DB connection successful to: " + dburl);
    }

    public void addPatient(Patient thePatient) throws Exception {
        PreparedStatement dbStmt = null;

        try {
            //prepare statement
            dbStmt = dbConn.prepareStatement("insert into patients " +
                     "(first_name, middle_name, last_name, phone_number, email) " +
                     "values (?, ?, ?, ?, ?)");

            // set params
            dbStmt.setString(1, thePatient.getFirstName());
            dbStmt.setString(2, thePatient.getMiddleName());
            dbStmt.setString(3, thePatient.getLastName());
            dbStmt.setObject(4, thePatient.getPhneNum());
            dbStmt.setString(5, thePatient.getEmail());

            // execute the query
            dbStmt.executeUpdate();

        } finally {
            close(dbStmt);
        }
    }

    public List<Patient> getAllPatients() throws Exception {
        List<Patient> list = new ArrayList<>();

        Statement dbStmt = null;
        ResultSet dbRs = null;

        try {
            dbStmt = dbConn.createStatement();
            dbRs = dbStmt.executeQuery("select * from patients");

            while (dbRs.next()) {
                Patient tempPatient = convertRowToPatient(dbRs);
                list.add(tempPatient);
            }

            return list;

        } finally {
            close(dbStmt, dbRs);
        }
    }

    public List<Patient> searchPatients(String firstName, String lastName) throws Exception {
        List<Patient> list = new ArrayList<>();

        PreparedStatement dbStmt = null;
        ResultSet dbRs = null;

        try {
            firstName += "%";
            lastName += "%";
            dbStmt = dbConn.prepareStatement("select * from patients where first_name like ? and last_name like ?");

            dbStmt.setString(1, firstName);
            dbStmt.setString(2, lastName);

            dbRs = dbStmt.executeQuery();

            while (dbRs.next()) {
                Patient tempPatient = convertRowToPatient(dbRs);
                list.add(tempPatient);
            }

            return list;
        } finally {
            close(dbStmt, dbRs);
        }
    }

    private Patient convertRowToPatient(ResultSet dbRs) throws SQLException {

        int id = dbRs.getInt("id");
        String firstName = dbRs.getString("first_name");
        String middleName = dbRs.getString("middle_name");
        String lastName = dbRs.getString("last_name");
        String phneNum = dbRs.getString("phone_number");
        String email = dbRs.getString("email");

        Patient tempPatient = new Patient(firstName, middleName, lastName, phneNum, email);

        return tempPatient;
    }

    private static void close(Connection dbConn, Statement dbStmt, ResultSet dbRs) throws SQLException {
        if (dbRs != null) 
            dbRs.close();

        if (dbStmt != null) 

        if (dbConn != null) 
            dbConn.close();
    }

    private static void close(Statement dbStmt, ResultSet dbRs) throws SQLException {
        close(null, dbStmt, dbRs);
    }

    private void close(Statement dbStmt) throws SQLException {
        close(null, dbStmt, null);      
    }

    public static void main(String[] args) throws Exception {

        PatientDAO dao = new PatientDAO();

        System.out.println(dao.getAllPatients());
    }
}

//UI Package
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.EventQueue;
import java.awt.FlowLayout;

import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JScrollPane;

import java.util.List;

import com.patientsessiontracker.core.*;
import com.patientsessiontracker.dao.*;

public class PatientSessionTrackerApp extends JFrame {

    private JPanel contentPane;
    private JTextField txtFieldSrchFName;
    private JButton btnSearch;
    private JScrollPane scrollPane;
    private static JTable table;

    private static PatientDAO patientDAO;
    private JPanel panelBtn;
    private JButton btnAddPatient;
    private JTextField txtFieldSrchLName;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    PatientSessionTrackerApp frame = new PatientSessionTrackerApp();
                    frame.setVisible(true);
                    PatientSessionTrackerApp.refreshPatientsView();
                    table.getColumnModel().getColumn(3).setCellRenderer(new PatientSessionTrackerCellRenderer());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public PatientSessionTrackerApp() {

        // create the DAO
        try {
            patientDAO = new PatientDAO();
        } catch (Exception exc) {
            JOptionPane.showMessageDialog(this, "Error: " + exc, "Error", JOptionPane.ERROR_MESSAGE); 
        }

        setTitle("Patient Session Tracker");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(600, 300);
        setResizable(false);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        JPanel panelSrch = new JPanel();
        panelSrch.setBounds(5, 5, 579, 33);
        contentPane.add(panelSrch);
        panelSrch.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));

        JLabel lblFirstName = new JLabel("First Name");
        panelSrch.add(lblFirstName);

        txtFieldSrchFName = new JTextField();
        panelSrch.add(txtFieldSrchFName);
        txtFieldSrchFName.setColumns(13);

        btnSearch = new JButton("Search");
        btnSearch.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                // Get last & first name from the text field

                // Call DAO and get patients for the last & first name

                // If last & first name is empty, then get all patients             

                try {
                    String firstName = txtFieldSrchFName.getText();
                    String lastName = txtFieldSrchLName.getText();

                    List<Patient> patients = null;

                    if (((firstName != null) && (firstName.trim().length() > 0)) ||
                        ((lastName != null) && (lastName.trim().length() > 0))) 
                        patients = patientDAO.searchPatients(firstName, lastName);
                    else
                        patients = patientDAO.getAllPatients();

                    // create the model and update the "table"
                    PatientTableModel model = new PatientTableModel(patients);

                    table.setModel(model);
                    table.getColumnModel().getColumn(3).setCellRenderer(new PatientSessionTrackerCellRenderer());

                } catch (Exception exc) {
                    JOptionPane.showMessageDialog(PatientSessionTrackerApp.this, "Error: " + exc, "Error", JOptionPane.ERROR_MESSAGE); 
                }

            }
        });

        JLabel lblLastName = new JLabel("Last Name");
        panelSrch.add(lblLastName);

        txtFieldSrchLName = new JTextField();
        panelSrch.add(txtFieldSrchLName);
        txtFieldSrchLName.setColumns(13);
        panelSrch.add(btnSearch);

        scrollPane = new JScrollPane();
        scrollPane.setBounds(5, 38, 579, 186);
        contentPane.add(scrollPane);

        table = new JTable();
        scrollPane.setViewportView(table);

        panelBtn = new JPanel();
        panelBtn.setBounds(5, 224, 579, 38);
        contentPane.add(panelBtn);

        btnAddPatient = new JButton("Add Patient");
        btnAddPatient.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                // create dialog
                AddPatientDialog addPatient = new AddPatientDialog(PatientSessionTrackerApp.this, patientDAO);

                // show dialog
                addPatient.setModal(true);
                addPatient.setVisible(true);
            }
        });
        panelBtn.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
        panelBtn.add(btnAddPatient);
    }

    public static void refreshPatientsView() {

        try {
            List<Patient> patients = patientDAO.getAllPatients();

            // create the model and update the "table"
            PatientTableModel model = new PatientTableModel(patients);

            table.setModel(model);
        } catch (Exception exc) {
            JOptionPane.showMessageDialog(null, "Error: " + exc, "Error",
                    JOptionPane.ERROR_MESSAGE);
        }

    }
}

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.FlowLayout;

import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

import com.patientsessiontracker.core.*;
import com.patientsessiontracker.dao.*;

public class AddPatientDialog extends JDialog {

    private final JPanel contentPanel = new JPanel();
    private JTextField txtFieldFName;
    private JTextField txtFieldMName;
    private JTextField txtFieldLName;
    private JTextField txtFieldAreaCode;
    private JTextField txtFieldPhneNum;
    private JTextField txtFieldPhnePrefix;
    private JTextField txtFieldEmail;

    private PatientDAO patientDAO;

    private PatientSessionTrackerApp patientSessionTrackerApp;

    public AddPatientDialog(PatientSessionTrackerApp thePatientSessionTracker, PatientDAO thePatientDAO) {
        this();
        patientDAO = thePatientDAO;
        patientSessionTrackerApp = thePatientSessionTracker;
    }

    public final class LengthRestrictedDocument extends PlainDocument {

          private final int limit;

          public LengthRestrictedDocument(int limit) {
            this.limit = limit;
          }

          @Override
          public void insertString(int offs, String str, AttributeSet a)
              throws BadLocationException {
            if (str == null)
              return;

            if ((getLength() + str.length()) <= limit) {
              super.insertString(offs, str, a);
            }
          }
        }

    /**
     * Create the dialog.
     */
    public AddPatientDialog() {
        setSize(450, 300);
        setResizable(false);
        setTitle("Add New Patient");
        getContentPane().setLayout(new BorderLayout());
        contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
        getContentPane().add(contentPanel, BorderLayout.CENTER);
        contentPanel.setLayout(null);
        {
            JLabel lblFName = new JLabel("<html>First Name<font color='red'>*</font></html>");
            lblFName.setBounds(10, 11, 104, 14);
            contentPanel.add(lblFName);

            txtFieldFName = new JTextField();
            txtFieldFName.setBounds(124, 8, 310, 20);
            contentPanel.add(txtFieldFName);
            txtFieldFName.setColumns(10);

            JLabel lblMName = new JLabel("Middle Name");
            lblMName.setBounds(10, 36, 104, 14);
            contentPanel.add(lblMName);

            txtFieldMName = new JTextField();
            txtFieldMName.setBounds(124, 33, 310, 20);
            contentPanel.add(txtFieldMName);
            txtFieldMName.setColumns(10);

            JLabel lblLName = new JLabel("<html>Last Name<font color='red'>*</font></html>");
            lblLName.setBounds(10, 61, 104, 14);
            contentPanel.add(lblLName);

            txtFieldLName = new JTextField();
            txtFieldLName.setBounds(124, 58, 310, 20);
            contentPanel.add(txtFieldLName);
            txtFieldLName.setColumns(10);

            JLabel lblPhneNum = new JLabel("Phone Number");
            lblPhneNum.setBounds(10, 86, 104, 14);
            contentPanel.add(lblPhneNum);

            JLabel labelLP = new JLabel("(");
            labelLP.setBounds(124, 86, 12, 14);
            contentPanel.add(labelLP);

            txtFieldAreaCode = new JTextField();
            txtFieldAreaCode.setBounds(134, 83, 28, 20);
            contentPanel.add(txtFieldAreaCode);
            txtFieldAreaCode.setColumns(10);
            txtFieldAreaCode.setDocument(new LengthRestrictedDocument(3));
        }

        JLabel labelRP = new JLabel(")");
        labelRP.setBounds(166, 86, 12, 14);
        contentPanel.add(labelRP);

        txtFieldPhneNum = new JTextField();
        txtFieldPhneNum.setBounds(210, 83, 35, 20);
        contentPanel.add(txtFieldPhneNum);
        txtFieldPhneNum.setColumns(10);
        txtFieldPhneNum.setDocument(new LengthRestrictedDocument(4));

        txtFieldPhnePrefix = new JTextField();
        txtFieldPhnePrefix.setColumns(10);
        txtFieldPhnePrefix.setBounds(172, 83, 28, 20);
        contentPanel.add(txtFieldPhnePrefix);
        txtFieldPhnePrefix.setDocument(new LengthRestrictedDocument(3));

        JLabel lblDash = new JLabel("-");
        lblDash.setBounds(202, 83, 12, 14);
        contentPanel.add(lblDash);

        JPanel buttonPane = new JPanel();
        buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
        getContentPane().add(buttonPane, BorderLayout.SOUTH);
        {
            JButton okButton = new JButton("Add Patient");
            okButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent arg0) {
                    savePatient();
                }
            });
            okButton.setActionCommand("OK");
            buttonPane.add(okButton);
            getRootPane().setDefaultButton(okButton);
        }

        JTextArea txtAddPatientWarning = new JTextArea();
        txtAddPatientWarning.setText("WARNING!!! Once a patient is created it is added to the database and cannot be removed from the database via the Patient Session Tracker. If a patient is added in error, please contact Sudo Technologies at (701) 388-3752.");
        txtAddPatientWarning.setBounds(10, 132, 424, 60);
        txtAddPatientWarning.setEditable(false);
        txtAddPatientWarning.setBackground(Color.YELLOW);
        txtAddPatientWarning.setLineWrap(true);
        contentPanel.add(txtAddPatientWarning);

        JLabel lblEmail = new JLabel("Email");
        lblEmail.setBounds(10, 110, 46, 14);
        contentPanel.add(lblEmail);

        txtFieldEmail = new JTextField();
        txtFieldEmail.setColumns(10);
        txtFieldEmail.setBounds(124, 107, 310, 20);
        contentPanel.add(txtFieldEmail);

        JLabel lblRqrdField = new JLabel("<html><font color='red'>*</font> Denotes Required Field</html>");
        lblRqrdField.setBounds(10, 213, 235, 26);
        contentPanel.add(lblRqrdField);
    }

    protected void savePatient() {

        // get the patient info from the gui
        String firstName = txtFieldFName.getText();
        String middleName = txtFieldMName.getText();
        String lastName = txtFieldLName.getText();
        //PhoneNumber phneNum = new PhoneNumber(txtFieldAreaCode.getText(), txtFieldPhnePrefix.getText(), txtFieldPhneNum.getText());
        String areaCode = txtFieldAreaCode.getText();
        String prefix = txtFieldPhnePrefix.getText();
        String num = txtFieldPhneNum.getText();
        String phneNum = areaCode + prefix + num;
        String email = txtFieldEmail.getText();

        Patient tempPatient = new Patient(firstName, middleName, lastName, phneNum, email);

        if ((firstName.trim().length() != 0) && (lastName.trim().length() != 0)) {  

            try{
                // save to the database
                patientDAO.addPatient(tempPatient);

                // close dialog
                setVisible(false);
                dispose();

                // refresh gui list
                patientSessionTrackerApp.refreshPatientsView();

                // show success message
                JOptionPane.showMessageDialog(patientSessionTrackerApp, "Patient added to the database.", 
                    "Patient Added",
                    JOptionPane.INFORMATION_MESSAGE);
            } catch (Exception exc) {
                JOptionPane.showMessageDialog(patientSessionTrackerApp, 
                        "Error saving patient: " +
                        exc.getMessage(), "Error",
                        JOptionPane.ERROR_MESSAGE);
            } 
        } else 
            JOptionPane.showMessageDialog(patientSessionTrackerApp, "<html>Please fill in all required fields as denoted by the <font color='red'>*</font>.</html>");
    }
}

import java.awt.Component;

import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;

import com.patientsessiontracker.core.*;

public class PatientSessionTrackerCellRenderer extends DefaultTableCellRenderer {
    private static final long serialVersionUID = 1L;
    public String areaCode;
    public String prefix;
    public String num;

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, 
                                                   boolean hasFocus, int row, int column) {
        Component cellComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        PhoneNumber phneNum = (PhoneNumber) value;
        String text =  "(" + phneNum.areaCode + ") " + phneNum.prefix + "-" + phneNum.num;
        setHorizontalAlignment(SwingConstants.CENTER);
        setText(text);
        return this;
    }
}

import javax.swing.table.AbstractTableModel;

import java.util.List;

import com.patientsessiontracker.core.*;

class PatientTableModel extends AbstractTableModel {

    private static final int FIRST_NAME_COL = 0;
    private static final int MIDDLE_NAME_COL = 1;
    private static final int LAST_NAME_COL = 2;
    private static final int PHONE_NUMBER_COL = 3;
    private static final int EMAIL_COL = 4;

    private String[] columnNames = {"First Name", "Middle Name", "Last Name", "Phone Number", "Email"};

    private List<Patient> patients;

    public PatientTableModel(List<Patient> thePatients) {
        patients = thePatients;
    }

    @Override
    public int getColumnCount() {
        return columnNames.length;
    }

    @Override
    public int getRowCount() {
        return patients.size();
    }

    @Override
    public String getColumnName(int col) {
        return columnNames[col];
    }

    @Override
    public Object getValueAt(int row, int col) {

        Patient tempPatient = patients.get(row);

        switch (col) {
        case FIRST_NAME_COL:
            return tempPatient.getFirstName();
        case MIDDLE_NAME_COL:
            return tempPatient.getMiddleName();
        case LAST_NAME_COL:
            return tempPatient.getLastName();
        case PHONE_NUMBER_COL:
            return tempPatient.getPhneNum();
        case EMAIL_COL:
            return tempPatient.getEmail();
        default:
            return tempPatient.getFirstName();
        }
    }

    @Override
    public Class getColumnClass(int c) {
        return getValueAt(0, c).getClass();
    }
}

我尝试将它作为一个对象传递给 DAO,但我还没有找到解决方案。当 运行 我得到错误:

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: java.lang.String cannot be cast to com.patientsessiontracker.core.PhoneNumber
    at com.patientsessiontracker.ui.PatientSessionTrackerCellRenderer.getTableCellRendererComponent(PatientSessionTrackerCellRenderer.java:22)

正如异常告诉您的那样,您不能将 String 转换为 PhoneNumber 对象。当你这样做时这里发生了什么

PhoneNumber phneNum = (PhoneNumber) value;

您将需要一种将字符串解析为 phone 数字对象的方法。现在,如果您不强制以特定格式输入 phone 数字,这可能会很棘手。如果是,那么您可以在 PhoneNumber 中创建一个方法来将字符串解析为 phone 数字。类似于:

public PhoneNumber parsePhoneNumber(String phoneStr){
    // Insert logic to extract your area code, prefix and number
    return new PhoneNumber(aC, pref, num);
}

但是我看到您将 phone 号码作为 3 个号码的串联存储在数据库中...这意味着解析字符串几乎是不可能的。

您应该考虑在整个代码中使用 PhoneNumber 对象。例如在你的 Patient 而不是 String

public class Patient {

    private int id;
    private String firstName;
    private String middleName;
    private String lastName;
    private PhoneNumber phneNum;
    private String email;

    public Patient(String firstName, String middleName, String lastName, PhoneNumber phneNum, String email) {
         this(0, firstName, middleName, lastName, phneNum, email);
    }

    public Patient(int id, String firstName, String middleName, String lastName, PhoneNumber phneNum, String email) {
        super();
        this.id = id;
        this.firstName = firstName;
        this.middleName = middleName;
        this.lastName = lastName;
        this.phneNum = phneNum;
        this.email = email;
   }
//....

那么您唯一需要担心转换的地方就是在读取和写入数据库时​​。