JTable自定义单元格编辑器验证后无法退出编辑及弹窗异常问题
解决JTable自定义单元格编辑器的两个问题
你遇到的两个问题:输入有效值后单元格仍处于编辑状态,以及弹窗提示导致应用挂起,我来帮你逐一解决。
问题分析
- 有效值输入后单元格仍可编辑:你的
stopCellEditing方法直接返回isValid,但没有调用父类的super.stopCellEditing(),这会导致DefaultCellEditor无法完成编辑状态的清理工作(比如移除编辑器组件、更新表格模型等),所以单元格看起来还处于编辑状态。 - 弹窗提示导致应用挂起:你使用
null作为JOptionPane的父组件,这会让弹窗成为无主窗口,可能在后台显示,同时因为表格的编辑状态未处理完成,导致事件派发线程阻塞,应用挂起。
修改后的完整代码
import javax.swing.*; import javax.swing.border.LineBorder; import java.awt.*; public class DepartmentCellEditor extends DefaultCellEditor { public DepartmentCellEditor() { super(new JTextField()); } @Override public boolean stopCellEditing() { JTable table = (JTable) getComponent().getParent(); try { boolean isValid = true; String s = getCellEditorValue().toString(); // 验证是否为3位数字 if (s.length() == 3) { for (int i = 0; i < s.length(); i++) { if (!Character.isDigit(s.charAt(i))) { isValid = false; break; } } } else { isValid = false; } JTextField textField = (JTextField) getComponent(); if (!isValid) { // 输入无效:设置红色边框,选中内容,保持焦点 textField.setBorder(new LineBorder(Color.RED)); textField.selectAll(); textField.requestFocusInWindow(); // 使用table作为父组件显示弹窗,避免后台挂起 SwingUtilities.invokeLater(() -> { JOptionPane.showMessageDialog(table, "Please enter a 3 digit number.", "Alert!", JOptionPane.ERROR_MESSAGE); }); return false; // 不停止编辑 } else { // 输入有效:恢复黑色边框,调用父类方法完成编辑停止 textField.setBorder(new LineBorder(Color.BLACK)); // 调用父类的stopCellEditing确保完成编辑状态清理 return super.stopCellEditing(); } } catch (ClassCastException exception) { JTextField textField = (JTextField) getComponent(); textField.setBorder(new LineBorder(Color.RED)); textField.selectAll(); textField.requestFocusInWindow(); SwingUtilities.invokeLater(() -> { JOptionPane.showMessageDialog((JTable) getComponent().getParent(), "Invalid input type.", "Alert!", JOptionPane.ERROR_MESSAGE); }); return false; } } @Override public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { Component c = super.getTableCellEditorComponent(table, value, isSelected, row, column); ((JComponent) c).setBorder(new LineBorder(Color.BLACK)); return c; } }
关键修改点说明
- 解决编辑状态未结束问题:当输入有效时,不再直接返回
true,而是调用super.stopCellEditing(),让DefaultCellEditor完成编辑停止的所有必要操作,比如更新表格模型、移除编辑器组件,这样单元格就会正常退出编辑状态。 - 解决弹窗挂起问题:
- 使用
table作为JOptionPane的父组件,确保弹窗在表格窗口的前方显示,不会跑到后台。 - 用
SwingUtilities.invokeLater()包裹弹窗代码,确保弹窗在事件派发线程的正确时机执行,避免阻塞编辑状态的处理流程。
- 使用
- 代码优化:将重复的JTextField获取逻辑提取出来,减少冗余代码。
这样修改后,输入3位有效数字时,单元格会正常退出编辑状态;输入无效值时,会显示弹窗提示,同时保持单元格的编辑状态和焦点,不会导致应用挂起。
内容的提问来源于stack exchange,提问作者Shahul Basha
相关产品推荐
相关产品推荐

