M
michael.o'connor
I have a JTable with editable columns, some of which should accept only
numbers. To do this, I have added a DefaultCellEditor to the numeric
columns, with a JTextField to accept user input, and a KeyListener to
filter out non-numeric keystrokes from the JTextField.
The user can start editing by mouse-clicking in a cell and typing, or
by navigating around the table using the arrow keys, then type in a
cell, without using the mouse.
All this works well, except in the second case when the user types in a
cell without first selecting it with the mouse. The problem here is
that the KeyListener does not see the first keystroke, but does see
subsequent ones. That means one non-numeric character can be entered
into the cell. However, the KeyListener always works if the user first
selects the cell with a mouse-click. Below is some code showing this
behaviour. What am I missing? How can I capture that first keystroke? I
am using Java 1.5.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class Test extends JFrame {
public Test() {
JTable table = new JTable(new Object[][] { {"a",1,2},{"b",3,4} },
new String[] {"Text", "Num 1", "Num 2"});
table.setRowSelectionAllowed(false);
table.setSurrendersFocusOnKeystroke(true);
TableColumnModel cm = table.getColumnModel();
cm.getColumn(1).setCellEditor(new MyCellEditor());
cm.getColumn(2).setCellEditor(new MyCellEditor());
JScrollPane scrollPane = new JScrollPane(table);
getContentPane().add(scrollPane);
}
private class MyCellEditor extends DefaultCellEditor {
private final JTextField tf;
public MyCellEditor() {
super(new JTextField());
tf = (JTextField) getComponent();
tf.addKeyListener(new MyKeyListener ());
setClickCountToStart(1);
}
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
tf.setText(value.toString());
return tf;
}
public Object getCellEditorValue() {
return tf.getText();
}
}
private class MyKeyListener implements KeyListener {
public void keyPressed(KeyEvent e) {}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {
if ( ! Character.isDigit(e.getKeyChar()) ) {
Toolkit.getDefaultToolkit().beep();
e.consume();
}
}
}
public static void main(String[] args) {
Test frame = new Test();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Mike
numbers. To do this, I have added a DefaultCellEditor to the numeric
columns, with a JTextField to accept user input, and a KeyListener to
filter out non-numeric keystrokes from the JTextField.
The user can start editing by mouse-clicking in a cell and typing, or
by navigating around the table using the arrow keys, then type in a
cell, without using the mouse.
All this works well, except in the second case when the user types in a
cell without first selecting it with the mouse. The problem here is
that the KeyListener does not see the first keystroke, but does see
subsequent ones. That means one non-numeric character can be entered
into the cell. However, the KeyListener always works if the user first
selects the cell with a mouse-click. Below is some code showing this
behaviour. What am I missing? How can I capture that first keystroke? I
am using Java 1.5.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class Test extends JFrame {
public Test() {
JTable table = new JTable(new Object[][] { {"a",1,2},{"b",3,4} },
new String[] {"Text", "Num 1", "Num 2"});
table.setRowSelectionAllowed(false);
table.setSurrendersFocusOnKeystroke(true);
TableColumnModel cm = table.getColumnModel();
cm.getColumn(1).setCellEditor(new MyCellEditor());
cm.getColumn(2).setCellEditor(new MyCellEditor());
JScrollPane scrollPane = new JScrollPane(table);
getContentPane().add(scrollPane);
}
private class MyCellEditor extends DefaultCellEditor {
private final JTextField tf;
public MyCellEditor() {
super(new JTextField());
tf = (JTextField) getComponent();
tf.addKeyListener(new MyKeyListener ());
setClickCountToStart(1);
}
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
tf.setText(value.toString());
return tf;
}
public Object getCellEditorValue() {
return tf.getText();
}
}
private class MyKeyListener implements KeyListener {
public void keyPressed(KeyEvent e) {}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {
if ( ! Character.isDigit(e.getKeyChar()) ) {
Toolkit.getDefaultToolkit().beep();
e.consume();
}
}
}
public static void main(String[] args) {
Test frame = new Test();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Mike