JTable使用JTextPane自定义编辑器单击编辑失效问题咨询
问题根因
- 首先是
terminateEditOnFocusLost配置的触发逻辑:开启该属性后,JTable会为单元格编辑器绑定焦点监听器,只要编辑器组件失去焦点就自动调用stopCellEditing终止编辑。Swing默认的JTextField编辑器会被JTable内部做特殊兼容,不会将表格内部的焦点切换判定为「外部失焦」,但自定义的JTextPane编辑器没有这套兼容处理。 - 其次是单击编辑的焦点时序冲突:单击单元格触发编辑的流程为:表格接收鼠标事件→判定可编辑→添加JTextPane到单元格→JTextPane默认主动请求焦点。如果界面上存在其他可聚焦组件(比如示例中底部的JTextField),Swing焦点管理器处理转移时会出现极短的临时焦点漂移,被失焦监听器捕获后直接终止刚启动的编辑,所以表现为单击无法进入编辑。
- 两次
stopCellEditing调用的来源:第一次是编辑启动时的焦点漂移误触发,第二次是切换到其他列时编辑器真实失焦触发。移除其他可聚焦组件后没有焦点漂移的情况,逻辑自然恢复正常。
解决方案
不需要修改terminateEditOnFocusLost配置,任选以下一种方案即可:
方案1:延迟JTextPane的焦点请求,避开时序冲突
修改MyCellEditor的getTableCellEditorComponent方法,等JTable的编辑初始化逻辑完全执行完成后,再让JTextPane请求焦点,避免触发误判:
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int rowIndex, int vColIndex) { comp.setText((String)value); // 加入延迟队列,等表格初始化完成后再请求焦点 SwingUtilities.invokeLater(() -> { if (comp.isShowing()) { comp.requestFocusInWindow(); // 可选:自动选中编辑器内的文本 comp.selectAll(); } }); return comp; }
方案2:给JTextPane添加JTable默认编辑器标记
JTable会识别组件的JTable.editor客户端属性,只要标记为true就会按照默认编辑器的规则做焦点兼容,不会误判失焦:
// 初始化编辑器时添加标记 JTextPane textPane = new JTextPane(); textPane.putClientProperty("JTable.editor", Boolean.TRUE); MyCellEditor myCellEditor = new MyCellEditor(textPane);
两种方案都可以解决单击无法编辑、stopCellEditing被调用两次的问题,同时保留业务配置。
内容的提问来源于stack exchange,提问作者simis Sim
相关产品推荐
相关产品推荐

