TableModel setCellEditable并自动将值设置回false

我正在尝试在我的JTable中实现一个JPopupMenu,允许解锁一个单元格进行编辑

@Override public void actionPerformed(ActionEvent e){ if(e.getActionCommand() == "Unlock"){ pTableModel.setCellEditable(this.getSelectedRow(), this.getSelectedColumn(), true); } } 

这是TableModel中的相关方法

 public void setCellEditable(int row, int col, boolean value) { editableCells[row][col] = value; this.fireTableCellUpdated(row, col); // I don't think I actually need this //because nothing in the cell has changed yet? } 

然后isCellEditable()返回editableCells [] []数组的值。 但是在我的代码中,当焦点丢失时,我应该将单元格更改为无法编辑?

在一个稍微相关的说明中,我也想让细胞立即获得焦点。 我已经阅读了关于getEditorComponent().requestFocus() – 但这似乎不太对,因为当时没有编辑任何内容,只选择了单元格(并使用该方法抛出nullpointerexception,这似乎支持我的想法处理)。

有人能指出我正确的方向吗? 我看不出哪里出错了。 谢谢

**编辑:为了在焦点丢失时锁定单元格,我尝试使用focusListener添加自定义cellrenderer:

 private class CustomCellRenderer extends DefaultTableCellRenderer{ public CustomCellRenderer(){ addFocusListener(new FocusAdapter(){ @Override public void focusLost(FocusEvent e) { pTableModel.setCellEditable(getSelectedRow(), getSelectedColumn(), false); } }); } } 

但这似乎也没有用,但我可能不正确地实现它(虽然我已经检查过渲染器已被添加)


SSCCE

 import java.awt.event.*; import java.util.*; import javax.swing.*; import javax.swing.table.AbstractTableModel; public class CellTest { public static void main(String[] args){ SwingUtilities.invokeLater(new Runnable(){ @Override public void run(){ createAndShowGUI(); } }); } private static void createAndShowGUI(){ JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); MyPanel panel = new MyPanel(); f.add(panel); f.pack(); f.setVisible(true); } } class MyPanel extends JPanel implements ActionListener{ private JTable table; private MyTableModel model; private JScrollPane sp; private List people; MyPanel(){ people = new ArrayList(); people.add(new Person("Will", 1)); model = new MyTableModel(people); table = new JTable(model); table.addMouseListener(new MouseAdapter(){ @Override public void mousePressed(MouseEvent e){ maybeShowPopup(e); } @Override public void mouseReleased(MouseEvent e){ maybeShowPopup(e); } }); table.setFillsViewportHeight(true); sp = new JScrollPane(table); this.add(sp); } @Override public void actionPerformed(ActionEvent e){ if(e.getActionCommand().equals("Unlock")) { model.setCellEditable(table.getSelectedRow(),table.getSelectedColumn(),true); } } private JPopupMenu createPopupMenu(){ JPopupMenu pop = new JPopupMenu(); JMenuItem item = new JMenuItem("Unlock"); item.addActionListener(this); pop.add(item); return pop; } private void maybeShowPopup(MouseEvent e){ int currentRow = table.rowAtPoint(e.getPoint()); if(currentRow >= 0 && currentRow < table.getRowCount()) table.setRowSelectionInterval(currentRow, currentRow); else table.clearSelection(); if(table.getSelectedRow() < 0) return; if(e.isPopupTrigger() && e.getComponent() instanceof JTable){ JPopupMenu pop = createPopupMenu(); pop.show(e.getComponent(), e.getX(), e.getY()); } } } 

而TableModel和数据类:

 class MyTableModel extends AbstractTableModel{ private List data; private String[] colNames = new String[]{"Name","Age"}; private boolean[][] editableCells; public MyTableModel(List data){ this.data = data; this.editableCells = new boolean[this.getRowCount()][this.getColumnCount()]; } @Override public int getRowCount() { return data.size(); } @Override public int getColumnCount() { return colNames.length; } @Override public Object getValueAt(int row, int col){ Person p = data.get(row); switch(col){ case 0 : return p.getName(); case 1 : return p.getAge(); } return null; } @Override public boolean isCellEditable(int row, int col){ return editableCells[row][col]; } public void setCellEditable(int row, int col, boolean value){ editableCells[row][col] = value; } @Override public void setValueAt(Object value, int row, int col){ Person p = data.get(row); switch(col){ case 0 : p.setName((String)value);break; case 1 : p.setAge((int)value);break; } this.setCellEditable(row, col, false); this.fireTableCellUpdated(row, col); } public void setData(List data){ this.data = data; this.fireTableDataChanged(); } } class Person { private String name; private int age; public Person(String name, int age){ this.name = name; this.age = age; } public void setName(String name){ this.name = name;} public String getName(){ return name; } public void setAge(int age){ this.age = age;} public int getAge(){ return age; } } 

道歉 – 我不知道如何缩短它,如果没有重新创建我想要实现的目标。 在这段代码中有一个错误,右键单击和“解锁”你必须左键单击一行,否则它们将是一个arrayIndexOutOfBoundsexception。 我还没找到确切的原因。

但基本上当你右键单击然后选择解锁时,我希望光标出现在单元格中。 此时,您单击解锁,然后必须双击该单元格。

但是在我的代码中,当焦点丢失时,我应该将单元格更改为无法编辑? –

你可以:

  1. 覆盖TableModel的setValueAt(...)方法,以便在更改数据后使单元格不可编辑。

  2. 使用TableModelListener当更新单元格的数据时,它将生成一个事件。