Wednesday, June 22, 2022

Java: Table with numeric input and length checks

Sample code showing how to do numeric input and character length checks with a JTable:


/*
* Table with numeric input and length checks.
* Şamil Korkmaz, June 2022
*/
package tablewithnumericinput;
import java.awt.Color;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.DefaultCellEditor;
import javax.swing.InputVerifier;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
public class TableWithNumericInput {
static private JTextField jtfForNumericFields;
static class MyKeyListener implements KeyListener {
@Override
public void keyTyped(KeyEvent ke) {
if (ke.getKeyCode() != KeyEvent.VK_BACK_SPACE && ke.getKeyCode() != KeyEvent.VK_DELETE) {
char c = ke.getKeyChar();
System.out.println("c = " + c);
System.out.println("Inside keyTyped()");
if (ke.getSource() instanceof JTextField) { //When user first double clicks on table and then presses a key, jtf will be the key event source
System.out.println("Key event source is text field");
} else if (ke.getSource() instanceof JTable) { //When table has focus but user has not double clicked on it, table will be the key event source
System.out.println("Key event source is table");
}
try {
Double.parseDouble(jtfForNumericFields.getText() + c); //getText() returns text before keypress, we have to add pressed key char to get full text
if (c == 'd' || c == 'f') { //parseDouble accepts 'd' and 'f' at the end of text
ke.consume(); //ignore key press
} else {
if (!jtfForNumericFields.getInputVerifier().verify(jtfForNumericFields)) { //check if text exceeds max nb of characters
ke.consume(); //ignore key press
}
}
} catch (NumberFormatException e) { //text is not a number
ke.consume(); //ignore key press
}
}
}
@Override
public void keyPressed(KeyEvent ke) {
}
@Override
public void keyReleased(KeyEvent ke) {
}
}
static class MyTable extends JTable {
public MyTable() {
putClientProperty("terminateEditOnFocusLost", true); //To make sure that setValue() is called when user clicks on another component, e.g. a button.
}
@Override
public void setValueAt(Object value, int iRow, int iColumn) {
if (value != null && ((String)value).length() > 0) {
if (iColumn > 0) {
double doubleValue = Double.parseDouble((String)value);
super.setValueAt(doubleValue, iRow, iColumn);
} else {
super.setValueAt(value, iRow, iColumn);
}
}
}
}
public static void main(String[] args) {
JFrame jf = new JFrame();
jf.setTitle("Table with numeric input checks");
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.getContentPane().setLayout(new javax.swing.BoxLayout(jf.getContentPane(), javax.swing.BoxLayout.PAGE_AXIS));
JTable jt = new MyTable();
jf.add(new JScrollPane(jt)); //to show table column headers
JButton jb = new JButton("OK");
jb.addActionListener((java.awt.event.ActionEvent evt) -> {
JOptionPane.showMessageDialog(jf, "Table contents: " + jt.getValueAt(0, 0) + ", " + jt.getValueAt(0, 1));
});
jf.add(jb);
jf.setBounds(100, 100, 400, 150);
jt.setBorder(javax.swing.BorderFactory.createLineBorder(Color.BLACK));
DefaultTableModel model = new DefaultTableModel() {
Class[] types = new Class[]{String.class, Double.class};
@Override
public Class getColumnClass(int iCol) {
return types[iCol];
}
};
jt.setModel(model);
model.addColumn("ID");
model.addColumn("Double Value");
model.addRow(new Object[]{});
final int PANEL_WIDTH = 200;
final int TABLE_HEIGHT = 3 * jt.getRowHeight();
jt.setBounds(0, jt.getRowHeight(), PANEL_WIDTH, TABLE_HEIGHT);
jt.getTableHeader().setBounds(0, 0, PANEL_WIDTH, jt.getRowHeight());
jtfForNumericFields = new JTextField();
jtfForNumericFields.setInputVerifier(new InputVerifier() {
@Override
public boolean verify(JComponent jc) {
JTextField jtf = (JTextField) jc;
String text = jtf.getText();
System.out.println("Text: " + text);
final int maxLength = 9;
if (text.length() > (maxLength - 1)) {
System.out.println("length > " + maxLength);
return false;
}
return true;
}
});
//Note that we have to add key listener to both table and text field because when
//table column 1 has focus and user presses a key, editing will start and table will catch
//key events. If user double click on column 1, then text field will catch key events:
jt.addKeyListener(new MyKeyListener());
jtfForNumericFields.addKeyListener(new MyKeyListener());
//Use numeric text field as editor for column 1 (second column):
jt.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(jtfForNumericFields));
jf.setVisible(true);
}
}

No comments:

Post a Comment