Sample code showing how to do numeric input and character length checks with a JTable:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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