title: JavaFX change node generated by FXML to another node
body: <p>I have a complicated UI defined by the fxml file. There are a lot of stock <code>TextField</code>s that I would like to change to more advanced versions (clearable text field) provided by <a href="https://github.com/controlsfx/controlsfx" rel="nofollow noreferrer">ControlsFX</a> library.</p>
  
  <p>The problem:</p>
  
  <p>ControlsFX uses <code>CustomTextField</code> to provide advanced features but it can only be initialized by <code>TextFields.createClearableTextField()</code> which can only be called from code.</p>
  
  <p>I am looking for a way to swap <code>TextField</code>s initialized via FXML with <code>CustomTextField</code>s initialized from code so that these new controls would retain all layout properties defined in FXML.</p>
  
  <p>Defining <code>CustomTextField</code> in FXML is also not helpful because by default it is useless.
  <code>CustomTextField</code> gains it's features via <code>private static void setupClearButtonField(TextField inputField, ObjectProperty&lt;Node&gt; rightProperty)</code> which i can't call because it's private.</p>
  
  <p>ControlsFX code:</p>
  
  <pre><code>/**
   * Creates a TextField that shows a clear button inside the TextField (on
   * the right hand side of it) when text is entered by the user.
   */
  public static TextField createClearableTextField() {
      CustomTextField inputField = new CustomTextField();
      setupClearButtonField(inputField, inputField.rightProperty());
      return inputField;
  }
  
  /**
   * Creates a PasswordField that shows a clear button inside the PasswordField
   * (on the right hand side of it) when text is entered by the user.
   */
  public static PasswordField createClearablePasswordField() {
      CustomPasswordField inputField = new CustomPasswordField();
      setupClearButtonField(inputField, inputField.rightProperty());
      return inputField;
  }
  
  private static void setupClearButtonField(TextField inputField, ObjectProperty&lt;Node&gt; rightProperty) {
      inputField.getStyleClass().add("clearable-field"); //$NON-NLS-1$
  
      Region clearButton = new Region();
      clearButton.getStyleClass().addAll("graphic"); //$NON-NLS-1$
      StackPane clearButtonPane = new StackPane(clearButton);
      clearButtonPane.getStyleClass().addAll("clear-button"); //$NON-NLS-1$
      clearButtonPane.setOpacity(0.0);
      clearButtonPane.setCursor(Cursor.DEFAULT);
      clearButtonPane.setOnMouseReleased(e -&gt; inputField.clear());
      clearButtonPane.managedProperty().bind(inputField.editableProperty());
      clearButtonPane.visibleProperty().bind(inputField.editableProperty());
  
      rightProperty.set(clearButtonPane);
  
      final FadeTransition fader = new FadeTransition(FADE_DURATION, clearButtonPane);
      fader.setCycleCount(1);
  
      inputField.textProperty().addListener(new InvalidationListener() {
          @Override public void invalidated(Observable arg0) {
              String text = inputField.getText();
              boolean isTextEmpty = text == null || text.isEmpty();
              boolean isButtonVisible = fader.getNode().getOpacity() &gt; 0;
  
              if (isTextEmpty &amp;&amp; isButtonVisible) {
                  setButtonVisible(false);
              } else if (!isTextEmpty &amp;&amp; !isButtonVisible) {
                  setButtonVisible(true);
              }
          }
  
          private void setButtonVisible( boolean visible ) {
              fader.setFromValue(visible? 0.0: 1.0);
              fader.setToValue(visible? 1.0: 0.0);
              fader.play();
          }
      });
  }
  </code></pre>