[英]Java Swing: How To Parse A Phone Number, Format It, And Display It In A JTable
我正在嘗試將JTable
的電話號碼列格式化為(Area) Prefix-Number
。 我不確定我做錯了什么,因為它可以正確編譯,並且根據getTableCellRenderer
教程和我仔細研究過的其他眾多示例來看,它們是否可以正常工作。 但這不是...在JTable中它仍然被格式化為一個字符串。
我首先接受來自一個文本字段的用戶輸入的電話號碼:
//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>");
}
}
然后,我嘗試將其傳遞給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;
}
}
從那里,我嘗試使用對象解析器在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;
}
}
最后,我嘗試在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);
}
}
}
電話號碼從MySQL database
的tinytext
列中存儲和檢索。 如果需要,可以隨時請求更多代碼,我破解了很多部分以嘗試縮短問題。
好的...我完全迷失了方向,對Java Swing毫無幫助。我嘗試將“電話號碼”類調用到Custom CellRenderer類中。 我得到的結果是(null)null-null。 我不確定自己做錯了什么,是否應該嘗試使用CustomCellRenderer教程中所示的MaskFormatter API? 這是經過修改的代碼:
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);
}
}
電話號碼類別:
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;
}
}
它可以毫無錯誤地進行編譯,並且根據getTableCellRenderer教程和我為之傾倒的其他眾多示例應該可以正常工作
問題是您沒有正確實現渲染器。 我建議您從有關使用自定義渲染器的Swing教程開始,以獲取適當的示例。
您創建的方法永遠不會被調用。 DefaultTableCellRenderer的getTableCellRendererComponent(...)
方法沒有將PhoneNumber
作為參數。 它有一個Object
。
每當您嘗試覆蓋方法時,請不要忘記@Override
注釋:
@Override
getTableCellRendererComponent(JTable table, PhoneNumber value, boolean isSelected, boolean hasFocus, int row, int column)
現在嘗試編譯您的代碼,因為您要覆蓋的方法的方法簽名不存在,您將收到錯誤消息。
要在渲染器中格式化數據,更簡單的方法是重寫渲染器的setValue(...)
方法。 該代碼將類似於:
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);
}
}
您可能要在PhoneNumber類中創建getFormattedPhoneNumber()
方法,以格式化的String形式返回電話號碼。 其他類不應真正直接訪問變量,而將數據格式化在單個位置始終是一個好主意。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.