【问题标题】:Can a Jtable save data whenever a cell loses focus?每当单元格失去焦点时,Jtable 可以保存数据吗?
【发布时间】:2009-10-31 00:23:50
【问题描述】:

高级:我有一个用户可以用来编辑数据的 JTable。

每当用户按下 Enter 或 Tab 完成编辑时,数据就会被保存(我假设“保存”实际上意味着“调用了 TableModel 的 setValueAt() 方法”。)

如果用户在进行编辑后以任何其他方式离开单元格,则不会保存新数据并且值保持原样。因此,例如,如果用户更改了一个值,然后单击屏幕上的某个其他小部件,则更改不会“坚持”。

我相信这是一个充满字符串的 JTable 的默认行为,是吗?

出于各种原因,所需的行为是让单元格在用户离开单元格时保存任何和所有编辑。让 Swing 执行此操作的最佳/正确方法是什么?

【问题讨论】:

    标签: java swing jtable


    【解决方案1】:

    Table Stop Editing 解释了发生的事情并提供了几个简单的解决方案。

    【讨论】:

      【解决方案2】:

      提出的简单解决方案之一

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

      仅适用于 String 列。问题是如果我有,例如,正在编辑的列的浮点类型,在相应的单元格中输入一个空字符串,然后单击窗口的任何其他控件 - Java 在CellEditorRemover.propertyChange()JTable.java 方法中抛出NullPointerException .它使用getCellEditor() 调用来停止或取消编辑,但在这种情况下它返回null。如果输入的值不为空,或者我删除了terminateEditOnFocusLost 标志,一切都很好。可能,描述的情况是一个错误。

      我希望我可以根据之前的一篇文章提供解决方案。它不像我之前想象的那么微不足道,但在我看来它确实有效。 我必须从默认单元格编辑器继承我自己的单元格编辑器,并从JTextField 继承我自己的文本字段FocusListener。当编辑单元格失去焦点并且窗口的另一个控件获得焦点时,此焦点侦听器工作正常。但是在单元格选择更改的情况下,焦点侦听器是“聋的”。这就是为什么我还必须在编辑开始之前记住以前的有效值,以便在输入的值无效时恢复它。

      请参阅下面的代码。使用DoubleFloatInteger 测试,但我希望这也适用于ByteString

      带有焦点监听器的文本字段:

      public class TextFieldCell extends JTextField {
          public TextFieldCell(JTable cellTable) {
              super();                            // calling parent constructor
              final JTable table = cellTable;     // this one is required to get cell editor and stop editing
      
              this.addFocusListener(new FocusListener() {
                  public void focusGained(FocusEvent e) {
                  }
      
                  // this function successfully provides cell editing stop
                  // on cell losts focus (but another cell doesn't gain focus)
                  public void focusLost(FocusEvent e) {
                      CellEditor cellEditor = table.getCellEditor();
                      if (cellEditor != null)
                          if (cellEditor.getCellEditorValue() != null)
                              cellEditor.stopCellEditing();
                          else
                              cellEditor.cancelCellEditing();
                  }
              });
          }
      }
      

      默认单元格编辑器类:

      class TextFieldCellEditor extends DefaultCellEditor {
      TextFieldCell textField;    // an instance of edit field
      Class<?> columnClass;       // specifies cell type class
      Object valueObject;         // for storing correct value before editing
      public TextFieldCellEditor(TextFieldCell tf, Class<?> cc) {
          super(tf);
          textField = tf;
          columnClass = cc;
          valueObject = null;
      }
      
      @Override
      public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
          TextFieldCell tf = (TextFieldCell)super.getTableCellEditorComponent(table, value, isSelected, row, column);
          if (value != null) {
              tf.setText(value.toString());
          }
          // we have to save current value to restore it on another cell selection
          // if edited value couldn't be parsed to this cell's type
          valueObject = value;
          return tf;
      }
      
      @Override
      public Object getCellEditorValue() {
          try {
              // converting edited value to specified cell's type
              if (columnClass.equals(Double.class))
                  return Double.parseDouble(textField.getText());
              else if (columnClass.equals(Float.class))
                  return Float.parseFloat(textField.getText());
              else if (columnClass.equals(Integer.class))
                  return Integer.parseInt(textField.getText());
              else if (columnClass.equals(Byte.class))
                  return Byte.parseByte(textField.getText());
              else if (columnClass.equals(String.class))
                  return textField.getText();
          }
          catch (NumberFormatException ex) {
      
          }
      
          // this handles restoring cell's value on jumping to another cell
          if (valueObject != null) {
              if (valueObject instanceof Double)
                  return ((Double)valueObject).doubleValue();
              else if (valueObject instanceof Float)
                  return ((Float)valueObject).floatValue();
              else if (valueObject instanceof Integer)
                  return ((Integer)valueObject).intValue();
              else if (valueObject instanceof Byte)
                  return ((Byte)valueObject).byteValue();
              else if (valueObject instanceof String)
                  return (String)valueObject;
          }
      
          return null;
      }
      

      表初始化的代码你必须添加以下内容:

      myTable.setDefaultEditor(Float.class, new TextFieldCellEditor(new TextFieldCell(myTable), Float.class));
      myTable.setDefaultEditor(Double.class, new TextFieldCellEditor(new TextFieldCell(myTable), Double.class));
      myTable.setDefaultEditor(Integer.class, new TextFieldCellEditor(new TextFieldCell(myTable), Integer.class));
      

      希望,这会帮助遇到同样问题的人。

      【讨论】:

        【解决方案3】:

        您需要添加focus listener。鉴于 JTable 基本上是其单元格组件的容器,因此您实际上希望表格中每个需要按照您指定的方式运行的单元格的焦点侦听器。

        为此,您需要创建自定义单元格编辑器,该编辑器包含已注册焦点侦听器的单元格组件。当您获得失去焦点事件的回调时,您会根据需要进行数据保存。

        This pretty much details most of what you need to do。没有实现焦点侦听器的细节,但这相当简单。

        假设您确实使用 JTextComponent 作为您的单元组件。那么:

        public void focusLost(FocusEvent e) {
           JTextComponent cell = (JTextComponent) e.getSource();  
           String data = cell.getText();
        
           // TODO: save the data for this cell
        }
        

        [附言。编辑]:

        使用此事件调用您的线程是调度线程。不要将它用于具有高延迟的操作。但如果你只是在堆中翻转位,应该没问题。

        【讨论】:

        • 在临时媒体上存储的集体知识背景下,人类需要吸取的教训。
        • Wayback Machine 拥有它——我相应地更改了链接。
        猜你喜欢
        • 2011-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-24
        • 1970-01-01
        • 1970-01-01
        • 2014-07-14
        • 1970-01-01
        相关资源
        最近更新 更多