简体   繁体   English

Java Swing:如何解析电话号码,对其进行格式化并将其显示在JTable中

[英]Java Swing: How To Parse A Phone Number, Format It, And Display It In A JTable

I am trying to format a phone number column in a JTable as (Area) Prefix-Number . 我正在尝试将JTable的电话号码列格式化为(Area) Prefix-Number I am not sure what I am doing wrong as it compiles without errors and according to the getTableCellRenderer tutorials and other numerous examples I've pored over it should work. 我不确定我做错了什么,因为它可以正确编译,并且根据getTableCellRenderer教程和我仔细研究过的其他众多示例来看,它们是否可以正常工作。 But it doesn't... it is still formatted as one string in the JTable. 但这不是...在JTable中它仍然被格式化为一个字符串。

I first accept user input from one text field for a phone number: 我首先接受来自一个文本字段的用户输入的电话号码:

//import necessary API

public class AddPatientDialog extends JDialog {

    private final JPanel contentPanel = new JPanel();
    private JTextField txtFieldPhneNum;

    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 lblPhneNum = new JLabel("Phone Number");
            lblPhneNum.setBounds(10, 86, 104, 14);
            contentPanel.add(lblPhneNum);
        }

        txtFieldPhneNum = new JTextField();
        txtFieldPhneNum.setBounds(124, 83, 86, 20);
        contentPanel.add(txtFieldPhneNum);
        txtFieldPhneNum.setColumns(10);
        txtFieldPhneNum.setDocument(new LengthRestrictedDocument(10));

        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 lblIe = new JLabel("Enter numbers only (i.e. 1234567890)");
        lblIe.setBounds(220, 86, 214, 14);
        contentPanel.add(lblIe);
    }

    protected void savePatient() {

        // get the patient info from the gui
        String firstName = txtFieldFName.getText();
        String middleName = txtFieldMName.getText();
        String lastName = txtFieldLName.getText();
        String phneNum = txtFieldPhneNum.getText();
        String email = txtFieldEmail.getText();

        Patient tempPatient = new Patient(phneNum);

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

I then try to pass it into a PhoneNumber class in order to try and parse the string: 然后,我尝试将其传递给PhoneNumber类,以尝试解析字符串:

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

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

    public PhoneNumber() {}

    public PhoneNumber parsePhoneNumber(String phneNum) {
        String[] phneNumArr = {phneNum.substring(0,3), phneNum.substring(3,6), phneNum.substring(6)};
        areaCode = phneNumArr[0];
        prefix = phneNumArr[1];
        num = phneNumArr[2];
        return new PhoneNumber(areaCode, prefix, num);
    }

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

From there I try to use the Object parser to format it in a CellRenderer class: 从那里,我尝试使用对象解析器在CellRenderer类中设置其格式:

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;
    public String phneNum;

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

Finally I attempt to implement the new format in the JTable: 最后,我尝试在JTable中实现新格式:

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) {        

                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();
            PatientTableModel model = new PatientTableModel(patients);

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

    }
}

The phone number gets stored and retrieved from a tinytext column in the MySQL database . 电话号码从MySQL databasetinytext列中存储和检索。 Feel free to ask for more code if needed, I hacked a lot of parts out to try and shorten the question. 如果需要,可以随时请求更多代码,我破解了很多部分以尝试缩短问题。


Okay... I am completely lost and admittedly a noob to Java Swing.I tried invoking the class Phone Number into the Custom CellRenderer Class. 好的...我完全迷失了方向,对Java Swing毫无帮助。我尝试将“电话号码”类调用到Custom CellRenderer类中。 What I get for a result is (null) null-null. 我得到的结果是(null)null-null。 I'm not sure what I am doing wrong, should I try using the MaskFormatter API as shown in the CustomCellRenderer tutorial? 我不确定自己做错了什么,是否应该尝试使用CustomCellRenderer教程中所示的MaskFormatter API? Here is the refractored code: 这是经过修改的代码:

CustomCellRenderer:
public class PatientSessionTrackerCellRenderer extends DefaultTableCellRenderer {
    private static final long serialVersionUID = 1L;

    public PatientSessionTrackerCellRenderer() {
        super();
        setHorizontalAlignment(SwingConstants.CENTER);
    }

    @Override
    public void setValue(Object value) {
        PhoneNumber phneNum = new PhoneNumber();
        value.toString();
        value =  "(" + phneNum.areaCode + ") " + phneNum.prefix + "-" + phneNum.num;

        super.setValue(value);
    }
}

PhoneNumber Class: 电话号码类别:

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

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

    public PhoneNumber() {}

    public PhoneNumber parsePhoneNumber(String value) {
        String[] phneNumArr = {value.substring(0,3), value.substring(3,6), value.substring(6)};
        areaCode = phneNumArr[0];
        prefix = phneNumArr[1];
        num = phneNumArr[2];
        return new PhoneNumber(areaCode, prefix, num);
    }

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

it compiles without errors and according to the getTableCellRenderer tutorials and other numerous examples I've poured over it should work 它可以毫无错误地进行编译,并且根据getTableCellRenderer教程和我为之倾倒的其他众多示例应该可以正常工作

The problem is that you haven't implemented the renderer correctly. 问题是您没有正确实现渲染器。 I suggest you start with the Swing tutorial on Using Custom Renderers for proper examples. 我建议您从有关使用自定义渲染器的Swing教程开始,以获取适当的示例。

The method you created is never invoked. 您创建的方法永远不会被调用。 The getTableCellRendererComponent(...) method of the DefaultTableCellRenderer does not have a PhoneNumber as a parameter. DefaultTableCellRenderer的getTableCellRendererComponent(...)方法没有将PhoneNumber作为参数。 It has an Object . 它有一个Object

Whenever you attempt to override a method don't forget the @Override annotation: 每当您尝试覆盖方法时,请不要忘记@Override注释:

@Override
getTableCellRendererComponent(JTable table, PhoneNumber value, boolean isSelected, boolean hasFocus, int row, int column)

Now try to compile your code and you will get an error because the method signature of the method you are attempting to override does not exist. 现在尝试编译您的代码,因为您要覆盖的方法的方法签名不存在,您将收到错误消息。

To format the data in a renderer the easier approach is override the setValue(...) method of the renderer. 要在渲染器中格式化数据,更简单的方法是重写渲染器的setValue(...)方法。 The code would be something like: 该代码将类似于:

public class PhoneNumberRenderer extends DefaultTableCellRenderer
{
    public PhoneNumberRenderer()
    {
        super();
        setHorizontalAlignment(SwingConstants.CENTER);
    }

    @Override
    public void setValue(Object value)
    {
        if (value instanceof PhoneNumber)
        {
            PhoneNumber pn = (PhoneNumber)value;
            value = "(" + pn.areaCode + ") " + pn.prefix" + "...";
        }

        super.setValue(value);
    }
}

You may want to create a getFormattedPhoneNumber() method in your PhoneNumber class to return the phone number in a formatted String. 您可能要在PhoneNumber类中创建getFormattedPhoneNumber()方法,以格式化的String形式返回电话号码。 Other classes should not really be accessing the variables directly and formatting the data in a single place is always a good idea. 其他类不应真正直接访问变量,而将数据格式化在单个位置始终是一个好主意。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM