java 仅在用户开始输入时清除 JavaFX TextField 中的提示文本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25125563/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 07:24:30  来源:igfitidea点击:

Clear prompt text in JavaFX TextField only when user starts typing

javauser-interfacejavafxtextfield

提问by Ramon

The default behaviour is that the prompt text in the field is erased as the field is being focused. That is when the marker is in the field.

默认行为是字段中的提示文本在字段获得焦点时被擦除。那是标记在现场的时候。

Is it possible to configure the textfield so the prompt text is only erased when the user have started typing?

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

Otherwise I need to add a label beside/over each textfield for description of the value in it.

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

回答by jewelsea

Solution

解决方案

This example will allow TextFields in JavaFX whose prompt behaviour is to show the prompt when the field is empty, even if the field has focus. The solution is a combination of custom CSS and a custom TextField class, which manipulates the css styles of the TextField.

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

promptpersist

提示坚持

persistent-prompt.css

持久提示.css

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

PersistentPromptTextField.java

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();
    }
}

PromptChanger.java

PromptChanger.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);
    }
}

How prompt handling is currently implemented in JavaFX 8

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

Default CSS for JavaFX 8 (modena.css) for controlling the prompt text is as follows:

用于控制提示文本的 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;
}

This will make the prompt text transparent whenever a field is focused, even if the field has no data in it.

这将使提示文本在聚焦字段时变得透明,即使该字段中没有数据。

In Comparison to HTML

与 HTML 的比较

HTML input has a placeholder, which is specified as follows:

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

User agents should present this hint to the user . . . when the element's value is the empty string or the control is not focused (or both).

用户代理应该向用户呈现这个提示。. . 当元素的值为空字符串或控件未获得焦点(或两者兼有)时。

You can try this functionality in your browser at this test link.

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

I think the argument against this behaviour for JavaFX "Prompt text should be cleared when focus is grabbed to signal readiness to receiving user input" is moot because focused text fields get a clearly visible focus ring, so the user knows that the control is ready to receive input even when the prompt text is displayed.

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

I think JavaFX should by default operate the same way as most HTML user agents in this respect. Feel free to create a Tweak request in the JavaFX issue trackerto request that the input prompt in JavaFX work similarly to HTML implementations (if there isn't an issue created for this already).

我认为 JavaFX 在默认情况下应该与大多数 HTML 用户代理在这方面的操作方式相同。随意在JavaFX 问题跟踪器中创建一个 Tweak 请求,以请求JavaFX中的输入提示的工作方式类似于 HTML 实现(如果尚未为此创建问题)。

Alternative

选择

The third party Gluon Glisten has a custom TextField controlcan have the following attributes:

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

  • Float Text- A place holder text inside a TextField which is transitioned to the top of the TextField when focus is received by it.
  • 浮动文本- TextField 内的占位符文本,当它接收到焦点时,它会转换到 TextField 的顶部。

The nice thing about the Glisten based TextField is that the prompt text is always visible, whether or not the user has typed anything into the control.

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

gluon rest

胶子静止

gluon active

胶子活性

回答by LionGod8

I know it's a bit old, but I needed it myself and this is still very relevant.
I will complete jewelsea's answer and give a simpler solution.

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

Background

背景

Apparently this was the default behavior of Java(FX) (prompt text in a TextField was cleared only when the user starts typing).
But then, following a request (or a bug report) in the JIRA system,
Java changed this behavior (and made the default to clear the text when the TextField gets focus).

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

You can review this bug report here.

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



Solution

解决方案

To get back to the old default (and nicer behavior IMO), all you need to do is to add the following line(s) of code.

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

In case your application interface is written using proper Java code.

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

Java Code:

Java代码:

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

Where textFieldis your TextField component.

textField您的 TextField 组件在哪里。



And in case your application interface is written using FXML and CSS, add the following to your CSS file.

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

JavaFX FXML (CSS):

JavaFX FXML (CSS):

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

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

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

Cleared-on-Focus Behavior

清除焦点行为

Currently it's the default behavior (the text-field's prompt text is cleared when the text-field gets focus),
so you don't need to do anything to get this behavior,
but in case Java will decide to go back to the cleared-on-typing behavior,
and you want to get the cleared-on-focus behavior, this is how to:

目前这是默认行为(当文本字段获得焦点时,文本字段的提示文本被清除),
因此您无需执行任何操作即可获得此行为
但以防 Java 决定返回到已清除的状态-打字行为,
并且您想获得清除焦点行为,这是如何:

In case of proper Java code - it's a bit tricky since you can't define behavior of pseudo-classes directly.

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

Java Code (using bindings):

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%);"));

or -

或者 -

Java Code (using events):

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:

JavaFX FXML CSS:

Add the following to your CSS file.

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

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

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

Hope this helped...

希望这有助于...

回答by Daniel h.

You could configure the '-fx-prompt-text-fill' key in '.text-field:focused' area like in '.text-field' area (css):

您可以在“.text-field:focused”区域中配置“-fx-prompt-text-fill”键,例如在“.text-field”区域(css)中:

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

and add the 'promptText' entry in fxml file:

并在 fxml 文件中添加“promptText”条目:

<TextField fx:id="XY_Id" promptText="First name">

That is all and works for me.

这就是全部并且对我有用。

回答by mohsenmadi

I am sure there may be several approaches and tricks to achieve what you're asking for, but, you are overriding a default, expected and standard UI behavior when you do so. Prompt text should be cleared when focus is grabbed to signal readiness to receiving user input, not after user starts typing.

我确信可能有几种方法和技巧可以实现您的要求,但是,当您这样做时,您将覆盖默认、预期和标准的 UI 行为。当获取焦点以表示准备好接收用户输入时,应清除提示文本,而不是在用户开始输入后。

回答by Forager

Assuming you're setting prompt text via:

假设您通过以下方式设置提示文本:

    @FXML TextField tf;

    public void someMethod() {
        tf.setPromptText("This is the prompt text");
    }

You can instead use tf.setText(String str)to set initial text.

您可以改为使用tf.setText(String str)来设置初始文本。

Then, in the initialize method of your controller, add:

然后,在控制器的 initialize 方法中,添加:

    tf.setOnKeyTyped(new EventHandler<KeyEvent>() {

        @Override
        public void handle(KeyEvent event) {
            tf.setText(null);

        }
    });

A link that you can refer to for additional help: Click me!

您可以参考以获得更多帮助的链接:单击我!