JTable 单元格更新不起作用

Posted

技术标签:

【中文标题】JTable 单元格更新不起作用【英文标题】:JTable Cell Update doesn't work 【发布时间】:2011-12-18 13:47:03 【问题描述】:

在我的应用程序中,我使用了一个类似于 this 示例的 java 表。我的问题是当我更改单元格的值时(即使在上面的示例中),数据模型在我单击不同的单元格之前不会更新。即使我在更改单元格值后单击表格下方的灰色区域,模型也不会更改。我认为原因是单元格保持专注,直到我点击另一个单元格。如何避免这种情况并在不单击表格单元格的情况下更新模型。提前致谢

我已经编辑了上面的示例代码以反映问题

public class JTableDemo extends JApplet 
  private JTextArea txt = new JTextArea(4, 20);

  // The TableModel controls all the data:
  class DataModel extends AbstractTableModel 
    Object[][] data =   "one", "two", "three", "four" ,
         "five", "six", "seven", "eight" ,
         "nine", "ten", "eleven", "twelve" , ;

    // Prints data when table changes:
    class TML implements TableModelListener 
      public void tableChanged(TableModelEvent e) 
        txt.setText(""); // Clear it
        for (int i = 0; i < data.length; i++) 
          for (int j = 0; j < data[0].length; j++)
            txt.append(data[i][j] + " ");
          txt.append("\n");
        
      
    

    public DataModel() 
      addTableModelListener(new TML());
       fireTableDataChanged();
    

    public int getColumnCount() 
      return data[0].length;
    

    public int getRowCount() 
      return data.length;
    

    public Object getValueAt(int row, int col) 
      return data[row][col];
    

    public void setValueAt(Object val, int row, int col) 
      data[row][col] = val;
      System.out.println(val);
      // Indicate the change has happened:
      fireTableDataChanged();
    

    public boolean isCellEditable(int row, int col) 
      return true;
    
  

  public void init() 
    Container cp = getContentPane();
    JTable table = new JTable(new DataModel());
    cp.add(new JScrollPane(table));
    cp.add(BorderLayout.SOUTH, txt);
  

  public static void main(String[] args) 
    run(new JTableDemo(), 350, 200);
  

  public static void run(JApplet applet, int width, int height) 
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(applet);
    frame.setSize(width, height);
    applet.init();
    applet.start();
    frame.setVisible(true);
  

运行示例时,您可以在表格下方的文本区域中看到表格内容。更新单元格后,它应该出现在下面的文本框中。但是在您单击不同的单元格之前,不会调用“setValueAt”方法。

【问题讨论】:

你能编辑你的问题并添加一个SSCCE来显示问题吗? 【参考方案1】:

这是预期的行为:编辑的值不会提交给支持模型,直到明确的用户手势,如 f.i.按回车键或跳出或单击表格中的其他位置...

JTable 的一个奇怪之处(有人称之为错误 :-) 是默认情况下,当将焦点转移到表格的“外部”时,编辑不会终止。要强制它这样做,您需要像这样配置它:

  table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);

顺便说一句(无关,只是为了理智):总是触发最细粒度的事件类型,这里是 cellUpdated 而不是 dataChanged 锤子。

【讨论】:

我喜欢你的星期一,很棒且有价值的回答 +1【参考方案2】:

默认更新机制仅在单元格编辑器失去焦点时更改模型。跳出单元格或单击不同的单元格都会导致触发模型更改的重要“焦点丢失”事件。

在灰色区域单击没有效果,因为那里没有可以处理事件的活动元素 - 表格忽略了单击。

如果你想改变它,你需要找到一个事件告诉计算机用户“完成编辑”。你怎么知道?

您可以添加ActionListener(请参阅http://download.oracle.com/javase/tutorial/uiswing/components/textfield.html)。当您按 RETURN 时,它将被触发。在处理程序中,调用fireEditingStopped() 以触发“复制到模型”代码(参见http://download.oracle.com/javase/tutorial/uiswing/components/table.html#editor)。

您可以在表格下方添加一个“保存”按钮,并在 ActionListner 中调用此代码:

if(null != jTable.getCellEditor()) 
    // there is an edit in progress
    jTable.getCellEditor().stopCellEditing()

您可以通过添加按键处理程序来更新每个按键的模型,但这可能会导致编辑器消失。

[编辑]请注意,添加“保存”按钮可能会扰乱用户的编辑“流程”(单击表格单元格、编辑、抓住鼠标、瞄准、单击保存、单击下一个单元格、转到返回键盘,编辑,...)

【讨论】:

只需添加一个不执行任何操作且带有“保存”标签的按钮。连同 kleopatra 的答案中的客户端属性,这应该可以解决问题。请注意,这会极大地惹恼您的用户,因为这意味着额外的鼠标点击。尝试添加助记符,以便人们可以使用“Alt+S”停止编辑(无需离开键盘)。 no: a focusLost 默认情况下不会 触发提交(这是一个长期存在的问题,直到他们可以确信至少支持选择性地设置它行为)。实际上,tab 或单击另一个单元格的提交是由 tableUI 代码显式触发的 @Kleo:您可能错过了“连同来自 kleopatra 答案的客户端属性”。如果这不起作用,您需要在按钮的单击处理程序中调用单元格编辑器的fireEditingStopped() 我已经按照以下方式完成了。当用户单击保存 actionListner 中的保存按钮时,我调用 jTable.getCellEditor().stopCellEditing();方法。 注意 jTable.getCellEditor() 将返回 null 如果没有“正在进行”编辑【参考方案3】:

对于我来说

public void setValueAt(Object val, int row, int col) 
  data[row][col] = val;
  System.out.println(val);
  // Indicate the change has happened:
  fireTableDataChanged();

你还需要调用超级函数。

public void setValueAt(Object val, int row, int col) 
  data[row][col] = val;
  System.out.println(val);
  // Indicate the change has happened:
  fireTableDataChanged();
  super.setValueAt(val,row,col);

【讨论】:

以上是关于JTable 单元格更新不起作用的主要内容,如果未能解决你的问题,请参考以下文章

滑动删除 UITableView 单元格动画在 swift 2 中不起作用

更新数据后 setContentOffset 不起作用

表格单元格中的 CSS 绝对定位在 Firefox 中不起作用

尽管蓝色,表格单元格尺寸不起作用

UICollectionView,单元格选择不起作用,单元格滚动正常

collectionView 单元格在 tapGestureRecognizer 函数中不起作用