2016-09-01 10 views
0

私はしばらく作業してきた編集可能なテーブルセルファクトリを使用しています。私は現在、編集を開始するためのシングルクリックを可能にする機能を実装しています。TableView JavaFxのすべてのセルに対してcancelEditを呼び出す

セル編集を開始するクリックが1回ありますが、別のセルを1回クリックすると前のページが閉じません。クリックしたセルを編集する前に、cancelEdit()を呼び出すすべてのセルをループすることが私の考えでした。

以下は、私が使用しているセルクラス全体です(ダブルクリックで編集しても問題ありません)。作業中のセクションはコンストラクタにあります。

public class EditingCell<S, T> extends TableCell<S, T> { 
    private TextField textField; 

    public EditingCell() { 
     TableView<S> table = this.getTableView(); 
     addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() { 
      @Override 
      public void handle(MouseEvent event) { 
       for(TableColumn<S, ?> col : table.getColumns()) { 
        // cancelEdit() on all cells here 
       } 
       startEdit(); 
      } 
     }); 
    } 

    public void commit(Object val) { 
     commit(val, this.getTableRow().getIndex(), getTableView().getColumns().indexOf(this.getTableColumn())); 
    } 

    @SuppressWarnings({ "unchecked", "rawtypes" }) 
    public void commit(Object val, int row, int col) { 

     // Get the table 
     TableView<S> t = this.getTableView(); 

     // Get the selected row/column 
     S selectedRow = t.getItems().get(row); 
     if (selectedRow == null) 
      return; 
     TableColumn<S, ?> selectedColumn = t.getColumns().get(col); 

     // Get current property name 
     String propertyName = ((PropertyValueFactory) selectedColumn.getCellValueFactory()).getProperty(); 

     // Create a method name conforming to java standards (setProperty) 
     propertyName = ("" + propertyName.charAt(0)).toUpperCase() + propertyName.substring(1); 

     // Try to run the update 
     try { 

      // Type specific checks - could be done inside each 
      // setProperty() method 
      if (val instanceof Double) { 
       Method method = selectedRow.getClass().getMethod("set" + propertyName, double.class); 
       method.invoke(selectedRow, (double) val); 
      } 
      if (val instanceof String) { 
       Method method = selectedRow.getClass().getMethod("set" + propertyName, String.class); 
       method.invoke(selectedRow, (String) val); 
      } 
      if (val instanceof Integer) { 
       Method method = selectedRow.getClass().getMethod("set" + propertyName, int.class); 
       method.invoke(selectedRow, (int) val); 
      } 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     // CommitEdit for good luck 
     commitEdit((T) val); 

     TableUtils.Refresh(t, t.getItems()); 

    } 

    @Override 
    public void startEdit() { 
     if (!isEmpty()) { 
      super.startEdit(); 
      createTextField(); 
      setText(null); 
      setGraphic(textField); 
      textField.selectAll(); 
     } 
    } 

    @Override 
    public void cancelEdit() { 
     super.cancelEdit(); 

     String val = "0.0"; 
     if (!textField.getText().equals("")) 
      val = "" + Double.parseDouble(textField.getText()); 

     setText(NumberUtils.roundTo2(NumberUtils.parseDouble(val)) + ""); 
     setGraphic(null); 

    } 

    @Override 
    public void updateItem(T item, boolean empty) { 
     super.updateItem(item, empty); 

     if (empty) { 
      setText(""); 
      setGraphic(null); 
     } else { 
      if (isEditing()) { 
       if (textField != null) { 
        textField.setText(getString()); 
       } 
       setText(null); 
       setGraphic(textField); 
      } else { 
       setText(NumberUtils.roundTo3(NumberUtils.parseDouble(getString())) + ""); 
       setGraphic(null); 
      } 
     } 
    } 

    @SuppressWarnings({ "rawtypes" }) 
    private void createTextField() { 
     textField = new TextField(getString()); 

     textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2); 
     textField.focusedProperty().addListener(new ChangeListener<Boolean>() { 

      @Override 
      public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2) { 
       if (!arg2) { 
        if (textField.getText().equals("")) 
         commit(0.0); 
        else { 
         double val = Double.parseDouble(textField.getText()); 
         commit(val); 
        } 
       } 
      } 
     }); 
     textField.addEventFilter(KeyEvent.KEY_PRESSED, event -> { 
      if (event.getCode() == KeyCode.ESCAPE) { 
       textField.setText("" + getItem()); 
       cancelEdit(); 
       event.consume(); 
      } 
      // Navigate up and down in table 
      else if (event.getCode() == KeyCode.ENTER) { 

       TableView<S> table = getTableView(); 
       int row = table.getEditingCell().getRow(); 

       // Commit changes 
       if (textField.getText().equals("")) 
        commit(0.0); 
       else { 
        double val = Double.parseDouble(textField.getText()); 
        commit(val); 
       } 

       // Do move 
       if (event.isShiftDown()) 
        table.edit(row - 1, getTableColumn()); 
       else { 
        table.edit(row + 1, getTableColumn()); 
       } 

      } 

      // Move left and right in table 
      else if (event.getCode() == KeyCode.TAB) { 
       TableView<S> table = getTableView(); 
       int row = table.getEditingCell().getRow(); 

       // Save changes 
       if (textField.getText().equals("")) 
        commit(0.0); 
       else { 
        double val = Double.parseDouble(textField.getText()); 
        commit(val); 
       } 

       ArrayList<TableColumn<S, ?>> cols = new ArrayList<TableColumn<S, ?>>(); 
       int index = 0; 
       for (TableColumn<S, ?> c : table.getColumns()) { 
        if (c.isVisible() && c.isEditable()) 
         cols.add(c); 
        if (c == getTableColumn()) 
         index = cols.size() - 1; 
       } 

       // Do move 
       if (event.isShiftDown()) { 
        try { 
         TableColumn<S, ?> prevCol = cols.get(index - 1); 
         table.edit(row, prevCol); 
        } catch (Exception e) { 
        } 
       } else { 
        try { 
         TableColumn<S, ?> nextCol = cols.get(index + 1); 
         table.edit(row, nextCol); 
        } catch (Exception e) { 
        } 
       } 
      } 
     }); 
     textField.setTextFormatter(new TextFormatter<String>((Change c) -> { 
      String text = c.getText(); 

      TableView<S> table = getTableView(); 
      if (table.getSelectionModel().getSelectedCells().size() == 0) { 
       return c; 
      } 
      TablePosition pasteCellPosition = table.getSelectionModel().getSelectedCells().get(0); 
      int clipRow = 0; 
      int clipCol = 0; 

      String curCellText = text; 

      if (text.contains("\t") || text.contains("\n")) { 

       StringTokenizer row = new StringTokenizer(text, "\n"); 
       boolean hasRun = false; 

       while (row.hasMoreTokens() || !hasRun) { 
        String r = row.nextToken(); 
        StringTokenizer col; 
        if (r != null) 
         col = new StringTokenizer(r, "\t"); 
        else 
         col = new StringTokenizer(text, "\t"); 

        hasRun = true; 
        clipCol = 0; 

        while (col.hasMoreTokens()) { 

         String content = col.nextToken(); 

         if (clipRow == 0 && clipCol == 0) { 
          curCellText = content; 
         } 

         // calculate the position in the table cell 
         int rowTable = pasteCellPosition.getRow() + clipRow; 
         int colTable = pasteCellPosition.getColumn() + clipCol; 

         // Skip hidden columns before current cell 
         for (int i = 0; i < colTable; i++) 
          if (!table.getColumns().get(i).isVisible()) 
           colTable++; 

         // Skip hidden columns between current and goal 
         while (!table.getColumns().get(colTable).isVisible()) { 
          if (colTable >= table.getColumns().size()) 
           break; 
          colTable++; 
         } 

         // Add row if we reach the end 
         if (rowTable >= table.getItems().size()) { 
          if (table.getItems().get(0) instanceof EditableTableRow) 
           ((EditableTableRow) table.getItems().get(0)).addRowToTable(table); 

          // continue; 
         } 
         if (colTable >= table.getColumns().size()) { 

          continue; 
         } 

         try { 
          double val = Double.parseDouble(content); 
          commit(val, rowTable, colTable); 

         } catch (Exception e) { 
          try { 
           int val = Integer.parseInt(content); 
           commit(val, rowTable, colTable); 
          } catch (Exception e2) { 
           commit(content, rowTable, colTable); 
          } 
         } 

         clipCol++; 
        } 

        clipRow++; 
       } 
      } 
      c.setText(curCellText); 

      return c; 
     })); 
     textField.requestFocus(); 
     textField.selectAll(); 
    } 

    private String getString() { 
     return getItem() == null ? "" : getItem().toString(); 
    } 
} 
+0

を行うことができますが、[TextFieldTableCell]を使用していない理由(http://docs.oracle.com/javaseがあります/8/javafx/api/javafx/scene/control/cell/TextFieldTableCell.html)クラス? – VGR

+0

主な理由 - 私はちょうど今存在していることを知りました.....しかし、私は機能に多くの変更を加えたので、それをそのままにしておくと思います。(表示された数字と実際の数字を切り取り、 – Chris

答えて

2

すべてのセルを反復処理することはできません。あなたはあなたが編集をキャンセルする効果があります

getTableView().edit(-1, null); 

を呼び出すことができます

、作成されたものを細胞知る方法はありません実際のアイテムを表している、など。 ( Javadocsを参照してください。)実際にだけではなく、 startEdit()を呼び出す

getTableView().edit(getIndex(), getTableColumn()); 

を呼び出すために、より良いかもしれません。これは(私は...テストしていないはずですか)startEdit()を呼び出します。言い換えれば、余談として

public EditingCell() { 
    addEventFilter(MouseEvent.MOUSE_CLICKED, e -> 
     getTableView().edit(getIndex(), getTableColumn())); 
} 

を行う、なぜあなたは、セルの実装は非常に一般的な作りが、その後のセル値の工場がPropertyValueFactoryのインスタンスであると仮定すると、すべてのトラブルに行くのですか?きっとあなたは

ObservableValue<T> obs = getTableColumn().getCellObservableValue(getTableView().getItems().get(getIndex())); 

でセル観察可能な値を取得してからちょうど

if (obs instanceof WritableValue) { 
    ((WritableValue<?>) obs).setValue(val); 
} 
+0

編集に関するアドバイスをいただき、ありがとうございます。私はJavaFxに慣れていないので、すべてのベストプラクティスを知ることができません。私はすべての行を非常に一般的に保っています。なぜなら、このテーブル・セルは、すべて異なる行クラスを持つ〜20種類の表に使用するからです。 – Chris

+0

私のセルの位置を取得するには良い方法は何ですか?私は編集を呼びたいと思っていますか? (私が 'startEdit'と呼んでいるのと同じコンストラクタで) – Chris

+0

' PropertyValueFactory'は、それ自体の中での伝統的で悪い習慣です。これは、ラムダ式を使用する前にコンビニエンスクラスとして記述されただけで、実質的に追加の冗長性を持たないカラムのプロパティを型指定可能に指定できます。 ; '。あなたの質問に答えるには、私が示したコードを使ってください:テーブルセルの 'getIndex()'は行のインデックスを与え、 'getTableColumn()'はテーブルの列を与えます。それらはまさに 'TableView.edit ...) 'ニーズ。 –

関連する問題