java - 如何通知 TableCellEditor 表行已删除?

标签 java swing jtable tablecelleditor abstracttablemodel

我尝试实现一个包含一些字段和删除按钮的 TableCellEditor。它运行良好,但当行被删除时,被删除单元格中的内容(使用 TableCellEditor 呈现)更新。

当删除行时,我尝试在模型中同时调用 fireTableRowsDeleted(row, row)fireTableDataChanged(),但它似乎没有通知表格单元格编辑器。当我选择另一行时它起作用,并且行索引再次使用 TableCellRenderer 呈现。

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

  1. 按下删除按钮

    enter image description here

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

    enter image description here

  3. 当再次使用 CellRenderer 时,行内容已更新。

    enter image description here

代码如下:

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();
            }
            
        });
    }
}

最佳答案

那是因为当您点击删除按钮时,您的 CellEditor 没有注意到它必须停止编辑单元格。

一个简单的解决方案是将另一个 ActionListener 添加到您的 CellEditor 并在您每次单击它时调用 stopCellEditing()。这应该有效:

public RendererAndEditor( StringTableModel model )
{
  renderer = new CellPanel( model );
  editor = new CellPanel( model );

  editor.getRemoveBtn().addActionListener( new ActionListener()
  {
    @Override
    public void actionPerformed( ActionEvent e )
    {
      stopCellEditing();
    }
  });
}

关于java - 如何通知 TableCellEditor 表行已删除?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8801210/

相关文章:

java - 多个 Super( ) 用于重载父类(super class)构造函数

java - 安卓安装异常 : EOF Google MapsView "Hello Maps"

java - 在Java中读取带有重音字符的文件

Java Swing 简单计算器没有正确添加

java - 动态地向 JTabbedPane 的不同选项卡中的多个 JTextAreas 添加文本?

java - 父类(super class)引用的访问修饰符和方法

java - 如何在netbeans中自定义swing UI设计

java - 在没有事件的情况下获取鼠标左键状态

java - JTable 通过单击同一 JTable 中具有自定义 DeleteCellEditor 的单元格来删除行

java - AWT-EventQueue-0“java.lang.ArrayIndexOutOfBoundsException : 0 error for JTable