JavaFX изменить узел, сгенерированный FXML, на другой узел - PullRequest
2 голосов
/ 15 апреля 2019

У меня сложный пользовательский интерфейс, определенный в файле fxml. Существует множество фондов TextField, которые я хотел бы изменить на более продвинутые версии (очищаемое текстовое поле), предоставляемые библиотекой ControlsFX .

Проблема:

ControlsFX использует CustomTextField для предоставления расширенных функций, но его можно инициализировать только с помощью TextFields.createClearableTextField(), который можно вызвать только из кода.

Я ищу способ поменять TextField s, инициализированный через FXML, на CustomTextField s, инициализированный из кода, чтобы эти новые элементы управления сохранили все свойства макета, определенные в FXML.

Определение CustomTextField в FXML также не полезно, потому что по умолчанию оно бесполезно. 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 Ответ

2 голосов
/ 15 апреля 2019

Вы можете использовать fx:factory, как описано в Введение в FXML .

<?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, но когда я запустил тестовый проект, все работало правильно.

...