JavaFX 将 FXML 生成的节点更改为另一个节点
JavaFX change node generated by FXML to another node
我有一个由 fxml 文件定义的复杂 UI。有很多股票 TextField
我想更改为 ControlsFX 库提供的更高级版本(可清除文本字段)。
问题:
ControlsFX 使用 CustomTextField
提供高级功能,但它只能由 TextFields.createClearableTextField()
初始化,只能从代码中调用。
我正在寻找一种方法来交换通过 FXML 初始化的 TextField
s 和从代码初始化的 CustomTextField
s,这样这些新控件将保留 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();
}
});
}
您可以按照 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,它会发出一条错误消息:
Cannot set org.controlsfx.control.textfield.TextFields to field 'field'
在 FXML 文件中,但是当我 运行 测试项目时一切正常。
我有一个由 fxml 文件定义的复杂 UI。有很多股票 TextField
我想更改为 ControlsFX 库提供的更高级版本(可清除文本字段)。
问题:
ControlsFX 使用 CustomTextField
提供高级功能,但它只能由 TextFields.createClearableTextField()
初始化,只能从代码中调用。
我正在寻找一种方法来交换通过 FXML 初始化的 TextField
s 和从代码初始化的 CustomTextField
s,这样这些新控件将保留 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();
}
});
}
您可以按照 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,它会发出一条错误消息:
Cannot set org.controlsfx.control.textfield.TextFields to field 'field'
在 FXML 文件中,但是当我 运行 测试项目时一切正常。