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
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.
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.
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);
}
}
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... */
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With