Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFX style class won't refresh

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 normal state:

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

but the style will stay the same as class selected

like image 268
user1236048 Avatar asked Jun 04 '12 20:06

user1236048


4 Answers

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.

like image 74
Walfrat Avatar answered Oct 18 '22 12:10

Walfrat


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.

like image 20
Uluk Biy Avatar answered Nov 18 '22 01:11

Uluk Biy


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);
    }
}
like image 1
L. BIZE Avatar answered Nov 18 '22 02:11

L. BIZE


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... */
}
like image 1
codepleb Avatar answered Nov 18 '22 01:11

codepleb