【问题标题】:JavaFX: Red border for text fieldJavaFX:文本字段的红色边框
【发布时间】:2014-08-05 13:33:39
【问题描述】:

我有一个带有文本字段的表单,如果我点击“保存”,我想给它们一个红色边框,但是例如在必填字段中没有输入任何内容,“生日”字段的字母,...。

我的文件: EditController.java,error.css

我已经试过了:

tfFirstName.getStyleClass().add("error");

,如果他们输入了有效的内容,则将其删除:

tfFirstName.getStyleClass().remove("error");

在css中:

.text-field.error {  
 -fx-border-color: red ;  
 -fx-border-width: 2px ;  
}

但这并没有改变任何东西。

令人惊讶的是,

tfFirstName.setStyle("-fx-border-color: red ; -fx-border-width: 2px ;");

(和一个空字符串来摆脱它)工作得很好,但如果我想稍后添加更多内容,它就不是“漂亮”了。

有人知道如何修复 css 吗?

【问题讨论】:

    标签: text javafx field border


    【解决方案1】:

    试试

    .text-field.error {
      -fx-text-box-border: red ;
      -fx-focus-color: red ;
    }
    

    第一个在不聚焦时设置边框颜色,第二个在聚焦时设置边框颜色。

    在样式表text-field-red-border.css 中有这个,下面的例子可以工作:

    import java.util.Collections;
    
    import javafx.application.Application;
    import javafx.beans.value.ChangeListener;
    import javafx.beans.value.ObservableValue;
    import javafx.collections.ObservableList;
    import javafx.scene.Scene;
    import javafx.scene.control.Label;
    import javafx.scene.control.TextField;
    import javafx.scene.layout.GridPane;
    import javafx.stage.Stage;
    
    public class ValidatingTextFieldExample extends Application {
    
        @Override
        public void start(Stage primaryStage) {
            GridPane root = new GridPane();
            TextField nameTF = new TextField();
            TextField emailTF = new TextField();
    
            root.add(new Label("Name:"), 0, 0);
            root.add(nameTF, 1, 0);
            root.add(new Label("Email:"), 0, 1);
            root.add(emailTF, 1, 1);
    
            setUpValidation(nameTF);
            setUpValidation(emailTF);
    
            Scene scene = new Scene(root, 250, 150);
            scene.getStylesheets().add(getClass().getResource("text-field-red-border.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        private void setUpValidation(final TextField tf) { 
            tf.textProperty().addListener(new ChangeListener<String>() {
    
                @Override
                public void changed(ObservableValue<? extends String> observable,
                        String oldValue, String newValue) {
                    validate(tf);
                }
    
            });
    
            validate(tf);
        }
    
        private void validate(TextField tf) {
            ObservableList<String> styleClass = tf.getStyleClass();
            if (tf.getText().trim().length()==0) {
                if (! styleClass.contains("error")) {
                    styleClass.add("error");
                }
            } else {
                // remove all occurrences:
                styleClass.removeAll(Collections.singleton("error"));                    
            }
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    顺便说一句,如果您使用的是 JavaFX 8,则更喜欢伪类而不是直接设置类,因为它更简洁(您不需要检查所有丑陋的代码,只需添加一次样式类和/或删除所有出现的样式它)和更有效。要设置和取消设置伪类:

    final PseudoClass errorClass = PseudoClass.getPseudoClass("error");
    
    tfFirstName.pseudoClassStateChanged(errorClass, true); // or false to unset it
    

    那么css应该是

    .text-field:error {
      -fx-text-box-border: red ;
      -fx-focus-color: red ;
    }
    

    (注意-text-fielderror 之间的冒号而不是.。)

    【讨论】:

    • 它也看起来像 "tfFirstName.setStyle("");"仅在设置后立即清除它。如果我以后想清除它,它会保留边界。
    • 你必须确保你没有多次添加样式类(或者当你清除它时一定要清除所有出现的)。样式类是一个列表,因此它可以保存重复值。
    • 更新了完整的例子。
    • 遗憾的是它不起作用,它从不显示红色边框。 java 和 css 位于不同的包中(java: java/client, css: resources/gui),并且验证是较早完成的。如果验证抛出异常,它只会得到一个红色边框,所以我将它分成 3 个部分:场景的“初始化”(=弹出)调用“setUpValidation”,在“catch”(异常)中调用“setRed() "(如果),当按下“确定”按钮以在验证之前清除所有内容时,我调用“其他”部分。 “setStyle”并不漂亮,但至少它有效,有没有办法再次将文本字段重置为默认值?
    • 感谢关于伪类的注释,不知道那些!
    【解决方案2】:

    当使用 javafx8 moderna 样式时,您可以使用这个 css 使边框类似于“聚焦”蓝色边框:

    .text-input.error {
        -fx-focus-color: #d35244;
        -fx-faint-focus-color: #d3524422;
    
        -fx-highlight-fill: -fx-accent;
        -fx-highlight-text-fill: white;
        -fx-background-color:
            -fx-focus-color,
            -fx-control-inner-background,
            -fx-faint-focus-color,
            linear-gradient(from 0px 0px to 0px 5px, derive(-fx-control-inner-background, -9%), -fx-control-inner-background);
        -fx-background-insets: -0.2, 1, -1.4, 3;
        -fx-background-radius: 3, 2, 4, 0;
        -fx-prompt-text-fill: transparent;
    }
    

    将 css 添加为类路径资源并使用以下方法加载它:

    scene.getStylesheets().add(
        getClass().getClassLoader().getResource(<your css resource path>).toString());
    

    然后将其应用于文本字段:

    // add error class (red border)
    textField.getStyleClass().add("error");
    // remove error class (red border)
    textField.getStyleClass().remove("error");
    

    【讨论】:

      【解决方案3】:

      James_D 的上述解决方案工作得非常好(但不适用于 JAVAFX 8.0)。 James 已经提到了 JAVAFX 8.0 的代码更改,我刚刚尝试过,它就像一个魅力。这是 JAVAFX 8.0 的更改版本,以防有人需要快速参考。所有信用都归 JAMES_D

      import java.util.Collections;
      
      import javafx.application.Application;
      import javafx.beans.value.ChangeListener;
      import javafx.beans.value.ObservableValue;
      import javafx.collections.ObservableList;
      import javafx.css.PseudoClass;
      import javafx.scene.Scene;
      import javafx.scene.control.Label;
      import javafx.scene.control.TextField;
      import javafx.scene.layout.GridPane;
      import javafx.stage.Stage;
      
      public class ValidatingTextFieldExample extends Application {
      private final PseudoClass errorClass = PseudoClass.getPseudoClass("error");
      @Override
      public void start(Stage primaryStage) {
          GridPane root = new GridPane();
          TextField nameTF = new TextField();
          TextField emailTF = new TextField();
      
          root.add(new Label("Name:"), 0, 0);
          root.add(nameTF, 1, 0);
          root.add(new Label("Email:"), 0, 1);
          root.add(emailTF, 1, 1);
      
          setUpValidation(nameTF);
          setUpValidation(emailTF);
      
          Scene scene = new Scene(root, 250, 150);
          scene.getStylesheets().add(getClass().getResource("text-field-red-border.css").toExternalForm());
          primaryStage.setScene(scene);
          primaryStage.show();
      }
      
      private void setUpValidation(final TextField tf) { 
          tf.textProperty().addListener(new ChangeListener<String>() {
      
              @Override
              public void changed(ObservableValue<? extends String> observable,
                      String oldValue, String newValue) {
                  validate(tf);
              }
      
          });
      
          validate(tf);
      }
      
      private void validate(TextField tf) {
          ObservableList<String> styleClass = tf.getStyleClass();
          if (tf.getText().trim().length()==0) {
              tf.pseudoClassStateChanged(errorClass, true);
          }
          else{
              tf.pseudoClassStateChanged(errorClass, false);
          }
      
      }
      
      public static void main(String[] args) {
          launch(args);
      }
      

      }

      【讨论】:

        【解决方案4】:

        有了这个,它现在可以正常工作了(它甚至不需要“setUpValidation”):

        public void initialize(URL arg0, ResourceBundle arg1) {
            removeRed(tfFirstName);
            removeRed(tfLastName);
        }
        
        public void OKButtonClicked() {
            try{
                //also: call validation class here
                removeRed(tfFirstName);
                removeRed(tfLastName);
            } catch(ValidationException e) {
                setRed(tfFirstName);
                setRed(tfLastName);
            }
        
        }
        
        private void setRed(TextField tf) {
            ObservableList<String> styleClass = tf.getStyleClass();
        
            if(!styleClass.contains("tferror")) {
                styleClass.add("tferror");
            }
        }
        
        
        private void removeRed(TextField tf) {
            ObservableList<String> styleClass = tf.getStyleClass();
            styleClass.removeAll(Collections.singleton("tferror"));
        }
        

        我在 css 中添加了以下内容(不幸的是,它不再使用“-fx-border-width: 2px”更改边框宽度):

        .tferror {  
             -fx-text-box-border: red ;
             -fx-focus-color: red ;   
        }
        

        【讨论】:

        • 呃,setUpValidation(...) 只是我编写的一种实用方法,用于在文本字段为空/非空时添加和删除红色边框。除了证明我的解决方案有效之外,它实际上与您的问题几乎没有关系。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-25
        • 2018-02-15
        • 1970-01-01
        • 2011-02-19
        • 2016-05-16
        • 2016-03-03
        相关资源
        最近更新 更多