【问题标题】:Clear prompt text in JavaFX TextField only when user starts typing仅当用户开始输入时清除 JavaFX TextField 中的提示文本
【发布时间】:2014-09-27 07:59:39
【问题描述】:

默认行为是字段中的提示文本在字段被聚焦时被删除。那是当标记在字段中时。

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

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

【问题讨论】:

    标签: java user-interface javafx textfield


    【解决方案1】:

    解决方案

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

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

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

    当前在 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 输入有一个placeholder,指定如下:

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

    您可以在浏览器中通过test link 试用此功能。

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

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

    替代方案

    第三方Gluon Glisten has a custom TextField control可以有以下属性:

    • 浮动文本- TextField 中的占位符文本,当它接收到焦点时,它会转换到 TextField 的顶部。

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

    【讨论】:

      【解决方案2】:

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

      背景

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

      您可以查看此错误报告here


      解决方案

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

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

      Java 代码:

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

      textField 是您的 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;
      }
      

      希望这有帮助...

      【讨论】:

        【解决方案3】:

        您可以在 '.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%);
        }`
        

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

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

        这就是全部,对我有用。

        【讨论】:

        • promptText 解决了我的问题,我无法在其他任何地方找到它。非常感谢!
        【解决方案4】:

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

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

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

        然后,在控制器的初始化方法中,添加:

            tf.setOnKeyTyped(new EventHandler<KeyEvent>() {
        
                @Override
                public void handle(KeyEvent event) {
                    tf.setText(null);
        
                }
            });
        

        您可以参考一个链接以获得更多帮助:Click me!

        【讨论】:

        • 目前我已经在SceneBuilder中设置了提示文字。我可以试试你提出的代码。
        【解决方案5】:

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

        【讨论】:

        • 是的,我完全意识到这一点,并且不想自己覆盖默认行为...我想我会在文本字段旁边/上方使用标签,并删除所有提示文本。跨度>
        猜你喜欢
        • 1970-01-01
        • 2011-09-17
        • 1970-01-01
        • 2017-08-09
        • 2015-01-04
        • 2013-08-08
        • 2020-07-20
        • 1970-01-01
        • 2017-09-12
        相关资源
        最近更新 更多