JavaFX style class won't refresh

前端 未结 5 1106
说谎
说谎 2021-02-08 05:08

I\'m adding a style class to an node if it\'s selected and then remove it if I select other item. Even if I remove the style class the style wont refresh so it wont go back to n

相关标签:
5条回答
  • 2021-02-08 05:33

    This is a bug. It is reported here Removal of hovered style class, does not update styling. You may want to vote and watch it. As a workaround you should override css rules you touched/changed to be the same as default ones. Demo:

    import javafx.application.Application;
    import javafx.event.ActionEvent;
    import javafx.event.EventHandler;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.control.Label;
    import javafx.scene.layout.StackPane;
    import javafx.scene.layout.VBoxBuilder;
    import javafx.stage.Stage;
    
    public class StyleDemo extends Application {
    
        @Override
        public void start(Stage primaryStage) {
            final Label lbl = new Label("Style Me");
            lbl.getStyleClass().add("style1"); // initial style
    
            Button btn = new Button("Change the style");
            btn.setOnAction(new EventHandler<ActionEvent>() {
    
                @Override
                public void handle(ActionEvent arg0) {
                    lbl.getStyleClass().remove("style1");
                    lbl.getStyleClass().add("style2");
                }
            });
    
            StackPane root = new StackPane();
            root.getChildren().add(VBoxBuilder.create().spacing(20).children(lbl, btn).build());
            Scene scene = new Scene(root, 300, 250);
            scene.getStylesheets().add(this.getClass().getResource("style.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    and the style.css is:

    .style1 {
        -fx-text-fill: red;
        -fx-border-color: green;
        -fx-font-size: 20;
    }
    
    .style2 {
        -fx-text-fill: blue;
        -fx-border-color: red;
        -fx-font-size: 15;
        -fx-underline: true;
    }
    

    when the button is clicked the initially added style1 is removed and the style2 is added.

    0 讨论(0)
  • 2021-02-08 05:37

    Thanks for the solution posted by Uluk Biy. But it seems not work "as is" (tested on jdk 1.70_40 win x 64). I have to clear style class before settings class. Here the working code for me:

    import javafx.application.Application;
    import javafx.beans.property.BooleanProperty;
    import javafx.beans.property.SimpleBooleanProperty;
    import javafx.event.ActionEvent;
    import javafx.event.EventHandler;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.control.Label;
    import javafx.scene.layout.StackPane;
    import javafx.scene.layout.VBoxBuilder;
    import javafx.stage.Stage;
    
    public class StyleDemo extends Application {
        //ADD just a toggle property
        public static BooleanProperty toggle = new SimpleBooleanProperty(false);
    
        @Override
        public void start(Stage primaryStage) {
            final Label lbl = new Label("Style Me");
            lbl.getStyleClass().add("style1"); // initial style
    
            Button btn = new Button("Change the style");
    
            btn.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    //ADD clear style class !
                    lbl.getStyleClass().clear();
                    if(toggle.get()) {
                        lbl.getStyleClass().add("style1");
                        toggle.set(!toggle.get());
                    }else{
                        lbl.getStyleClass().add("style2");
                        toggle.set(!toggle.get());
                    }
                }
            });
    
            StackPane root = new StackPane();
            root.getChildren().add(VBoxBuilder.create().spacing(20).children(lbl,btn).build());
            Scene scene = new Scene(root, 300, 250); 
            scene.getStylesheets().add("/style.css");
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    
    0 讨论(0)
  • 2021-02-08 05:51

    6 Years laters the bug is still there, here is a simpler way to go, specially if you won't want to mess with the other classes :

    int indexOf = textField.getStyleClass().indexOf(INVALID_CLASS);
    if(indexOf != -1){
        textField.getStyleClass().remove(indexOf);
    }
    

    Why this works ? Because the list used for StyleClass which is a TrackableObservablieList inherits from a hierarchy where the remove(index) does fire changes where the remove(Object) does not.

    0 讨论(0)
  • 2021-02-08 05:52

    You can try to add a css for the application instead. You can use even FXML to separate de design from the logic of your application. Here is a piece of code that worked for me in JavaFX 2.1!

    private Parent replaceSceneContent(String fxml) throws Exception {
       Parent page = (Parent)
          FXMLLoader.load(
             Main.class.getResource(fxml), null, new JavaFXBuilderFactory());
       Scene scene = stage.getScene();
       if (scene == null) {
          scene = new Scene(page, 1366, 720);
          scene.getStylesheets().add(
             Main.class.getResource(
                "../skinFolder/css/defaultSkin.css" ).toExternalForm());
          stage.setScene(scene);
       } else {
          stage.getScene().setRoot(page);
       }
       stage.sizeToScene();
       return page;
    }
    
    0 讨论(0)
  • 2021-02-08 05:56

    At least for Java 8, this works now. But instead of doing what the OP did, I would achieve the same like this:

    admin_category_label.getStyleClass().remove("selected");
    admin_category_label.getStyleClass().add("clear");
    

    Looks a bit cleaner.

    Remember, that your CSS selectors need to look like this:

    .selected {
        /* Styling attributes... */
    }
    
    .clear {
        /* Styling attributes... */
    }
    
    0 讨论(0)
提交回复
热议问题