问题
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
回答1:
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.
回答2:
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);
}
}
回答3:
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... */
}
回答4:
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;
}
回答5:
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.
来源:https://stackoverflow.com/questions/10887525/javafx-style-class-wont-refresh