仅在用户开始键入时清除 JavaFX 文本字段中的提示文本背景溶液清除对焦行为

2022-09-04 05:29:26

默认行为是在对字段进行聚焦时擦除字段中的提示文本。这是当标记在现场时。

是否可以配置文本字段,以便仅在用户开始键入时才删除提示文本?

否则,我需要在每个文本字段旁边/上方添加一个标签,以描述其中的值。


答案 1

我知道它有点旧,但我自己需要它,这仍然非常相关。
我将完成jewelsea的答案,并给出一个更简单的解决方案。

背景

显然,这是 Java(FX) 的默认行为(仅当用户开始键入时,TextField 中的提示文本才会被清除)。
但是,在JIRA系统中的请求(或错误报告)之后,
Java改变了这种行为(并默认在TextField获得焦点时清除文本)。

您可以在此处查看此错误报告。


溶液

要回到旧的默认值(以及更好的行为IMO),您需要做的就是添加以下代码行。

如果您的应用程序接口是使用正确的Java代码编写的。

Java 代码:

textField.setStyle("-fx-prompt-text-fill: derive(-fx-control-inner-background, -30%);");

文本字段组件位于何处。textField


如果您的应用程序接口是使用 FXML 和 CSS 编写的,请将以下内容添加到 CSS 文件中。

JavaFX FXML (CSS):

.text-input, .text-input:focused {
    -fx-prompt-text-fill: derive(-fx-control-inner-background, -30%);
}

--------------------------------------------------------------------------------

清除对焦行为

目前,这是默认行为(当文本字段获得焦点时,文本字段的提示文本将被清除),
因此您无需执行任何操作即可获得此行为
但是如果 Java 决定返回到在键入时清除行为,
并且您希望获得清除的对焦行为,请按照以下步骤操作:

在适当的Java代码的情况下 - 这有点棘手,因为你不能直接定义伪类的行为。

Java 代码(使用绑定):

textField.styleProperty().bind(
        Bindings
        .when(textField.focusedProperty())
            .then("-fx-prompt-text-fill: transparent;")
            .otherwise("-fx-prompt-text-fill: derive(-fx-control-inner-background, -30%);"));

或 -

Java 代码(使用事件):

textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
    @Override
    public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
        if (newValue) {
            textField.setStyle("-fx-prompt-text-fill: transparent;");
        } else {
            textField.setStyle("-fx-prompt-text-fill: derive(-fx-control-inner-background, -30%);");
        }
    }
});

JavaFX FXML CSS:

将以下内容添加到 CSS 文件中。

.text-input {
    -fx-prompt-text-fill: derive(-fx-control-inner-background, -30%);
}

.text-input:focused {
    -fx-prompt-text-fill: transparent;
}

希望这有帮助...


答案 2

溶液

此示例将允许 JavaFX 中的 TextFields,其提示行为是在字段为空时显示提示,即使该字段具有焦点也是如此。该解决方案是自定义 CSS 和自定义 TextField 类的组合,该类操作 TextField 的 css 样式。

promptpersist

持久提示符.css

.persistent-prompt:focused {
    -fx-prompt-text-fill: derive(-fx-control-inner-background,-30%);
}
.no-prompt {
    -fx-prompt-text-fill: transparent !important;
}

PersistentPromptTextField.java

import javafx.scene.control.TextField;

public class PersistentPromptTextField extends TextField {
    PersistentPromptTextField(String text, String prompt) {
        super(text);
        setPromptText(prompt);
        getStyleClass().add("persistent-prompt");
        refreshPromptVisibility();

        textProperty().addListener(observable -> refreshPromptVisibility());
    }

    private void refreshPromptVisibility() {
        final String text = getText();
        if (isEmptyString(text)) {
            getStyleClass().remove("no-prompt");
        } else {
            if (!getStyleClass().contains("no-prompt")) {
                getStyleClass().add("no-prompt");
            }
        }
    }

    private boolean isEmptyString(String text) {
        return text == null || text.isEmpty();
    }
}

提示转换器.java

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class PromptChanger extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        TextField textField1 = new PersistentPromptTextField("", "First name");
        TextField textField2 = new PersistentPromptTextField("", "Last name");

        VBox layout = new VBox(
                10,
                textField1,
                textField2
        );
        layout.setPadding(new Insets(10));

        Scene scene = new Scene(layout);
        scene.getStylesheets().add(
                getClass().getResource(
                        "persistent-prompt.css"
                ).toExternalForm()
        );
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        Application.launch(args);
    }
}

当前如何在 JavaFX 8 中实现提示处理

用于 JavaFX 8 (modena.css) 用于控制提示文本的默认 CSS 如下所示:

.text-input {
    -fx-prompt-text-fill: derive(-fx-control-inner-background,-30%);
}
.text-input:focused {
    -fx-prompt-text-fill: transparent;
}

这将使提示文本在字段获得焦点时保持透明,即使该字段中没有数据也是如此。

与 HTML 的比较

HTML 输入有一个占位符,其指定方式如下:

用户代理应将此提示呈现给用户 。 。 。当元素的值是空字符串或控件未获得焦点(或两者均未聚焦)时。

您可以在浏览器中的此测试链接中尝试此功能。

我认为针对JavaFX的这种行为“当焦点被抓取时应该清除提示文本以表示准备好接收用户输入”的论点是没有意义的,因为聚焦文本字段获得清晰可见的焦点环,因此用户知道即使显示提示文本,控件也准备好接收输入。

我认为JavaFX在这方面应该像大多数HTML用户代理一样运行。您可以随意在 JavaFX 问题跟踪器中创建一个 Tweak 请求,以请求 JavaFX 中的输入提示与 HTML 实现类似(如果尚未为此创建问题)。

另类

闪光

第三方 Gluon Glisten 具有自定义 TextField 控件,可以具有以下属性:

  • 浮动文本 - 文本字段中的占位符文本,当文本字段接收焦点时,该文本将转换到文本字段的顶部。

基于 Glisten 的 TextField 的好处在于,无论用户是否已在控件中键入任何内容,提示文本始终可见。

gluon rest

gluon active

MaterialFX

MaterialFX还为文本字段提示提供了多种替代实现,类似于Glisten操作,但与Google Material设计相匹配。要查看示例,请单击预览GIF中的“字段”演示选项。


推荐