Java 如何通知TableCellEditor表行已删除?

Java 如何通知TableCellEditor表行已删除?,java,swing,jtable,tablecelleditor,abstracttablemodel,Java,Swing,Jtable,Tablecelleditor,Abstracttablemodel,我尝试实现一个TableCellEditor,它包含一些字段和一个delete按钮。它工作正常,但删除行时,已删除单元格中的内容(使用TableCellEditor呈现)不会更新 我尝试在删除行时调用模型中的fireTableRowsDeleted(row,row)和fireTableDataChanged(),但它似乎没有通知TableCellEditor。当我选择另一行时,行索引会再次使用TableCellRenderer呈现 关于删除时如何通知TableCellEditor有什么建议吗 按

我尝试实现一个TableCellEditor,它包含一些字段和一个delete按钮。它工作正常,但删除行时,已删除单元格中的内容(使用TableCellEditor呈现)不会更新

我尝试在删除行时调用模型中的
fireTableRowsDeleted(row,row)
fireTableDataChanged()
,但它似乎没有通知TableCellEditor。当我选择另一行时,行索引会再次使用TableCellRenderer呈现

关于删除时如何通知TableCellEditor有什么建议吗

  • 按下删除按钮

  • 行已删除,但CellEditor内容未更新

  • 再次使用CellRenderer时,行内容已更新

  • 代码如下:

    public class StringTableDemo extends JFrame {
    
        public StringTableDemo() {
            
            final StringTableModel model = new StringTableModel();
            model.addRow("Jonas");
            model.addRow("Hello");
            model.addRow("World");
            
            RendererAndEditor rendererAndEditor = new RendererAndEditor(model);
            
            JTable table = new JTable(model);
            table.setDefaultRenderer(Record.class, rendererAndEditor);
            table.setDefaultEditor(Record.class, rendererAndEditor);
            
            add(new JScrollPane(table), BorderLayout.CENTER);
            pack();
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setVisible(true);
        }
        
        class Record {
            String string;
            boolean isDeleted;
        }
        
        class StringTableModel extends AbstractTableModel {
    
            private final List<Record> data = new ArrayList<Record>();
            
            @Override
            public int getColumnCount() {
                return 1;
            }
    
            @Override
            public int getRowCount() {
                return data.size();
            }
    
            @Override
            public Object getValueAt(int row, int column) {
                return data.get(row);
            }
            
            @Override
            public Class<?> getColumnClass(int column) {
                return Record.class;
            }
            
            @Override
            public boolean isCellEditable(int row, int column) {
                return true;
            }
            
            @Override
            public void setValueAt(Object aValue, int row, int column) {
                if(aValue instanceof Record) {
                    Record r = (Record)aValue;
                    if(!r.isDeleted) {
                        data.set(row, r);
                        fireTableRowsUpdated(row, column);
                    }
                } else throw new IllegalStateException("aValue is not a Record");
            }
            
            public void addRow(String s) {
                Record r = new Record();
                r.string = s;
                r.isDeleted = false;
                data.add(r);
                fireTableRowsInserted(data.size()-1, data.size()-1);
            }
            
            public void removeRow(int row) {
                data.remove(row);
                //fireTableRowsDeleted(row, row);
                fireTableDataChanged();
                
                System.out.println("row " + row + " deleted");
            }
    
        }
        
        class CellPanel extends JPanel {
            private final Action removeAction = new AbstractAction("x") {
    
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    model.removeRow(index);
                    isDeleted = true;
                }
                
            };
            private final JButton removeBtn = new JButton(removeAction);
            private final JTextField field = new JTextField();
            private final StringTableModel model;
            private int index;
            private boolean isDeleted = false;
            public CellPanel(StringTableModel model) {
                super(new BorderLayout());
                this.model = model;
                add(field, BorderLayout.CENTER);
                add(removeBtn, BorderLayout.EAST);
            }
            
            public Record getRecord() {
                Record r = new Record();
                r.string = field.getText();
                r.isDeleted = isDeleted;
                return r;
            }
            
            public void setRecord(Record r, int index) {
                field.setText(r.string);
                this.index = index;
            }
        }
        
        class RendererAndEditor extends AbstractCellEditor implements
         TableCellEditor, TableCellRenderer {
    
            private final CellPanel renderer;
            private final CellPanel editor;
            
            public RendererAndEditor(StringTableModel model) {
                renderer = new CellPanel(model);
                editor = new CellPanel(model);
            }
            
            @Override
            public Object getCellEditorValue() {
                return editor.getRecord();
            }
    
            @Override
            public Component getTableCellRendererComponent(JTable table,
                    Object value, boolean isSelected, boolean hasFocus, 
                           int row, int column) {
                
                renderer.setRecord((Record)value, row);
                return renderer;
            }
    
            @Override
            public Component getTableCellEditorComponent(JTable table, 
                    Object value, boolean isSelected, int row, int column) {
                editor.setRecord((Record)value, row);
                return editor;
            }
            
        }
    
        
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    new StringTableDemo();
                }
                
            });
        }
    }
    
    公共类StringTableDemo扩展JFrame{
    公共StringTableDemo(){
    最终StringTableModel模型=新StringTableModel();
    模型。addRow(“Jonas”);
    model.addRow(“你好”);
    模型。addRow(“世界”);
    RenderAndEditor RenderAndEditor=新的RenderAndEditor(模型);
    JTable table=新的JTable(模型);
    表.setDefaultRenderer(Record.class、renderAndEditor);
    table.setDefaultEditor(Record.class、renderAndEditor);
    添加(新的JScrollPane(表),BorderLayout.CENTER);
    包装();
    setDefaultCloseOperation(关闭时退出);
    setVisible(真);
    }
    课堂记录{
    字符串字符串;
    布尔值被删除;
    }
    类StringTableModel扩展了AbstractTableModel{
    私有最终列表数据=新的ArrayList();
    @凌驾
    public int getColumnCount(){
    返回1;
    }
    @凌驾
    public int getRowCount(){
    返回data.size();
    }
    @凌驾
    公共对象getValueAt(int行,int列){
    返回数据.get(行);
    }
    @凌驾
    公共类getColumnClass(int列){
    返回记录.class;
    }
    @凌驾
    公共布尔值可编辑(int行,int列){
    返回true;
    }
    @凌驾
    public void setValueAt(对象有效、整行、整列){
    if(记录的有效实例){
    记录r=(记录)aValue;
    如果(!r.isDeleted){
    数据集(行,r);
    fireTableRowsUpdated(行、列);
    }
    }否则抛出新的非法状态异常(“aValue不是记录”);
    }
    public void addRow(字符串s){
    记录r=新记录();
    r、 字符串=s;
    r、 isDeleted=假;
    数据。添加(r);
    fireTableRowsInserted(data.size()-1,data.size()-1);
    }
    公共无效清除器OW(int行){
    数据删除(行);
    //fireTableRowsDeleted(行,行);
    fireTableDataChanged();
    系统输出打印项次(“行”+行+“删除”);
    }
    }
    类CellPanel扩展了JPanel{
    私人最终行动removeAction=新抽象行动(“x”){
    @凌驾
    已执行的公共无效操作(操作事件arg0){
    模型.指数;
    isDeleted=真;
    }
    };
    私有最终JButton removeBtn=新JButton(removeAction);
    私有最终JTextField=新JTextField();
    私有最终模型;
    私有整数索引;
    私有布尔值isDeleted=false;
    公共单元面板(StringTableModel){
    超级(新边框布局());
    this.model=模型;
    添加(字段、边框布局、中心);
    添加(删除BTN,BorderLayout.EAST);
    }
    公共记录getRecord(){
    记录r=新记录();
    r、 string=field.getText();
    r、 isDeleted=isDeleted;
    返回r;
    }
    公共无效集合记录(记录r,整数索引){
    field.setText(r.string);
    这个指数=指数;
    }
    }
    类RenderAndEditor扩展了AbstractCellEditor实现
    TableCellEditor,TableCellRenderer{
    私人最终CellPanel渲染器;
    私人小组编辑;
    公共渲染器和编辑器(StringTableModel模型){
    渲染器=新单元面板(模型);
    编辑器=新单元面板(模型);
    }
    @凌驾
    公共对象getCellEditorValue(){
    返回editor.getRecord();
    }
    @凌驾
    公共组件GetTableCellRenderComponent(JTable表,
    对象值,布尔isSelected,布尔hasFocus,
    整数行,整数列){
    renderer.setRecord((记录)值,行);
    返回渲染器;
    }
    @凌驾
    公共组件getTableCellEditorComponent(JTable表,
    对象值,布尔值(选定,int行,int列){
    editor.setRecord((记录)值,行);
    返回编辑器;
    }
    }
    公共静态void main(字符串[]args){
    SwingUtilities.invokeLater(新的Runnable(){
    @凌驾
    公开募捐{
    新的StringTableDemo();
    }
    });
    }
    }
    
    这是因为当您单击删除按钮时,
    单元格编辑器
    没有注意到它必须停止编辑单元格

    一个简单的解决方案是向
    CellEditor
    添加另一个
    ActionListener
    ,并在每次单击它时调用
    StopCellEdit()
    。这应该起作用:

    public RendererAndEditor( StringTableModel model )
    {
      renderer = new CellPanel( model );
      editor = new CellPanel( model );
    
      editor.getRemoveBtn().addActionListener( new ActionListener()
      {
        @Override
        public void actionPerformed( ActionEvent e )
        {
          stopCellEditing();
        }
      });
    }
    
    顺便说一句,你的编辑是implem