Reputation: 177
I would like to check the validity of user input every time they change a value on the JTable. The method I thought of is similar to this simplified sample code:
public static void main(String[] args) {
JFrame main = new JFrame();
JTable table = new JTable(6, 4);
table.setSize(300, 300);
table.getModel().addTableModelListener((TableModelEvent e) -> {
Object s = e.getSource();
TableModel d = (TableModel) s;
if(!checkValid(d.getValueAt(e.getFirstRow(), e.getColumn())))
{
d.setValueAt(" - ", e.getFirstRow(), e.getColumn());
}
});
main.add(table);
main.setSize(300,300);
main.setLocationRelativeTo(null);
main.setVisible(true);
main.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
}
The code will check the input if a change in the table occurs and will revert back to "-" if the input is invalid.
However, an error will occur stating that Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
.
a.) Could someone explain the error and how to solve the issue?
b.) Or is there a better way of implementing a listener that checks the user input BEFORE exiting editing mode or saving the table?
EDIT: I have tried implementing the CellEditorListener like the sample below:
table.getCellEditor().addCellEditorListener(new CellEditorListener() {
public void editingStopped(ChangeEvent e)
{
}
public void editingCanceled(ChangeEvent e)
{
}
});
This in turn prompted an error Exception in thread "main" java.lang.NullPointerException
. There isn't that much of documentation on CellEditorListener and didn't quite understood on how it works and how to use it.
Upvotes: 1
Views: 183
Reputation: 3366
According to the corresponding section of the corresponding Java tutorials, you can override stopCellEditing
of DefaultCellEditor
to return false
if the editor should not lose focus or true
otherwise. Which means we can use it to check user input first and then, according to the user's input, return false
if he/she enters invalid text (or true
if he/she enters valid one).
In the following example code I'm using a JTextField
, which lets the users type whatever they want and then checks the user's input in stopCellEditing
to be non-empty (as defined by my static checkValid
method, but you can obviously alter it according to your needs):
import java.awt.Toolkit;
import javax.swing.DefaultCellEditor;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
public class Main {
public static boolean checkValid(final String text) {
return text != null && !text.trim().isEmpty(); //Your checks here...
}
public static class MyCellEditor extends DefaultCellEditor {
public MyCellEditor() {
super(new JTextField());
}
@Override
public boolean stopCellEditing() {
final JTextField field = (JTextField) getComponent();
if (checkValid(field.getText())) {
//field.setBackground(Color.WHITE);
return super.stopCellEditing(); //Fires 'editing stopped' event and returns true.
}
Toolkit.getDefaultToolkit().beep();
//field.setBackground(Color.ORANGE.darker());
JOptionPane.showMessageDialog(field, "You must enter a non-empty value!", "Oups!", JOptionPane.ERROR_MESSAGE);
return false;
}
}
public static void main(final String[] args) {
final JTable table = new JTable(new DefaultTableModel(10, 10));
table.setDefaultEditor(Object.class, new MyCellEditor());
final JFrame frame = new JFrame("JTable DefaultEditor");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(table);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
I use DefaultTableModel
for easy initialization of the table. It also returns that each cell in the table is editable (we obviously need at least one cell to be editable, in order to check the validity of the program). Every cell starts initially empty, but the cell editor won't let you leave it empty, if you start an editing event.
An alternative solution could be to add an InputVerifier
in the JTextField
of the editor, but this would be a bit more tricky as I tested it, so I would rather not post it here in favor of the better above solution (and also suggested by the Java tutorial).
Upvotes: 1