FXML生成的JavaFX将节点更改为另一个节点

时间:2019-04-15 19:31:26

标签: java javafx fxml controlsfx

我有一个由fxml文件定义的复杂UI。我想将许多库存TextField更改为ControlsFX库提供的更高级的版本(可清除的文本字段)。

问题:

ControlsFX使用CustomTextField提供高级功能,但只能通过TextFields.createClearableTextField()进行初始化,而只能通过代码进行调用。

我正在寻找一种方法,以将通过FXML初始化的TextField与通过代码初始化的CustomTextField交换,以便这些新控件保留FXML中定义的所有布局属性。

在FXML中定义CustomTextField也没有帮助,因为默认情况下它是无用的。 CustomTextField通过private static void setupClearButtonField(TextField inputField, ObjectProperty<Node> rightProperty)获得了它的功能,因为它是私有的,所以我无法调用。

ControlsFX代码:

/**
 * 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<Node> 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 -> 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() > 0;

            if (isTextEmpty && isButtonVisible) {
                setButtonVisible(false);
            } else if (!isTextEmpty && !isButtonVisible) {
                setButtonVisible(true);
            }
        }

        private void setButtonVisible( boolean visible ) {
            fader.setFromValue(visible? 0.0: 1.0);
            fader.setToValue(visible? 1.0: 0.0);
            fader.play();
        }
    });
}

1 个答案:

答案 0 :(得分:2)

您可以按照Introduction to FXML中的说明使用fx:factory

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.StackPane?>
<?import org.controlsfx.control.textfield.TextFields?>

<StackPane xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml"
           fx:controller="com.example.Controller">

    <TextFields fx:id="field" fx:factory="createClearableTextField"/>

</StackPane>

然后在控制器中使用它:

package com.example;

import javafx.fxml.FXML;
import javafx.scene.control.TextField;

public class Controller {

    @FXML private TextField field;

}

注意:如果您使用的是IntelliJ,它将发出错误消息:

  

无法将org.controlsfx.control.textfield.TextFields设置为字段'field'

在FXML文件中,但是当我运行测试项目时,一切正常。