You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在JTable中如何触发DefaultCellEditor.EditorDelegate的startCellEditing方法?

问题根源与修正方案

1. 为什么JTextField的MouseListener没触发?

JTable的单元格在未进入编辑状态时,显示的是单元格渲染器(TableCellRenderer),而非你定义的JTextField编辑器组件。只有当编辑真正启动后,编辑器组件才会被挂载到JTable的界面层级中并显示。因此你双击单元格时,点击的是渲染器组件,不是tf,自然触发不了tf上的MouseListener。

2. 为什么最初的startCellEditing方法没触发?

实际上这个方法会被触发,但你的代码存在两个问题:

  • 你只给第1列(Count列)绑定了自定义编辑器,只有双击该列的单元格才会触发这个方法,双击其他列不会有反应。
  • 你通过table.getSelectedRow()获取行号的方式不可靠:当通过键盘(比如按F2)触发编辑时,选中的行/列可能和编辑的单元格不一致,应该改用JTable的getEditingRow()和getEditingColumn()方法获取当前编辑的单元格位置。

修正后的代码

移除无用的MouseListener,修正startCellEditing中的单元格位置获取方式,同时去掉多余的文本设置逻辑(DefaultCellEditor会自动同步单元格值到编辑器):

import java.awt.*;
import java.awt.event.*;
import java.util.EventObject;
import javax.swing.*;
import javax.swing.table.*;

public class MonitorEditingStartStopped extends JFrame {

  public MonitorEditingStartStopped() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(220, 150);
    setLocationRelativeTo(null);

    String headers[] = {"Fruit", "Count", "Profit"};
    Object data[][] = {
        {"Apple", 6, -0.3},
        {"Banana", 3, 0.4},
        {"Cherry", 10, 1.},
        {"Date", -3, -1.}
      };

    DefaultTableModel model= new DefaultTableModel(headers, 0) {
      public Class<?> getColumnClass(int column) {
        Class<?> returnValue;
        if (getRowCount()>0 && getValueAt(0, column)!=null)
          returnValue= getValueAt(0, column).getClass();
        else
          returnValue= Object.class;
        return returnValue;
      }
    };
    for (int i=0; i<data.length; i++) {
      model.addRow(data[i]);
    }
    JTable table= new JTable(model);
    JTextField tf= new JTextField(10);
    tf.setHorizontalAlignment(SwingConstants.RIGHT);
    StartStopEditor editor= new StartStopEditor(table, tf);
    TableColumnModel tcm= table.getColumnModel();
    tcm.getColumn(1).setCellEditor(editor);
    JScrollPane scrollPane= new JScrollPane(table);
    add(scrollPane, BorderLayout.CENTER);
    setVisible(true);
  }


  public static void main(String args[]) {
    EventQueue.invokeLater(MonitorEditingStartStopped::new);
  }


  class StartStopEditor extends DefaultCellEditor {
    private final JTable table;

    public StartStopEditor(JTable table, JTextField tf) {
      super(tf);
      this.table = table;
      delegate= new EditorDelegate() {
        @Override
        public Object getCellEditorValue() {
          if (tf.getText().isBlank()) return Integer.valueOf(0);
          return Integer.valueOf(tf.getText());
        }

        @Override
        public boolean startCellEditing(EventObject anEvent) {
          // 使用JTable的getEditingRow/Column获取当前编辑的单元格位置
          int row= table.getEditingRow();
          int column= table.getEditingColumn();
          System.out.printf("started %d, %d%n", row, column);
          // 移除手动设置文本的逻辑,DefaultCellEditor会自动同步值到tf
          return super.startCellEditing(anEvent);
        }

        @Override
        public boolean stopCellEditing() {
          System.out.printf("editing stopped %d%n", getCellEditorValue());
          return super.stopCellEditing();
        }
      };
    }
  }

}

额外说明

如果你想监听所有单元格的编辑开始事件,除了重写prepareEditor,也可以通过给JTable添加CellEditorListener实现:

table.getDefaultEditor(Object.class).addCellEditorListener(new CellEditorListener() {
    @Override
    public void editingStopped(ChangeEvent e) {
        // 编辑结束逻辑
    }

    @Override
    public void editingCanceled(ChangeEvent e) {
        // 编辑取消逻辑
    }
});

不过针对特定列的编辑器,你写的自定义EditorDelegate方式更直接。

内容的提问来源于stack exchange,提问作者Jörg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 09:24:52