I want to customize a Slider
and found a working example here on stackoverflow:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class SliderWithLabeledThumb extends Application {
@Override
public void start(Stage primaryStage) {
Slider slider = new Slider();
StackPane root = new StackPane(slider);
root.setPadding(new Insets(20));
Scene scene = new Scene(root);
slider.applyCss();
slider.layout();
Pane thumb = (Pane) slider.lookup(".thumb");
Label label = new Label();
label.textProperty().bind(slider.valueProperty().asString("%.1f"));
thumb.getChildren().add(label);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Unfortunately, if I look up the thumb of the slider in my controller class for an fxml view, I will always get a NullPointerException
when trying to add the Label
to the thumb
's children… Thumb can obviously not be looked up. Then I found another answer here that says lookup()
must be called after stage.show()
, so here is my question again:
How can I look up a slider thumb in a controller class that manages fxml components (that does not have a stage.show()
)?
I tried creating a Slider
in code only and also used one from fxml, both lookups return null
when calling that in the controller's initialize(…)
method.
Is it somehow possible to customize a Slider
's thumb in a controller class?
EDIT:
The code that produces the exception is in the controller class that gets automatically instantiated due to an entry in the corresponding xml file. No matter if I use a Slider
loaded from fxml by annotation, having just a member and initialize that or create a new Slider
object. As long as I do that in the controller class, I will keep getting NullPointerExceptions
from the line commented in the code below:
public class MainViewController implements Initializable {
@FXML private VBox root;
private Slider timeSlider;
@Override
public void initialize(URL location, ResourceBundle resources) {
timeSlider = new Slider();
root.getChildren.add(timeSlider);
timeSlider.setMax(360);
timeSlider.setMin(0);
timeSlider.setCursor(Cursor.OPEN_HAND);
timeSlider.applyCss();
timeSlider.layout();
Pane thumb = (Pane) timeSlider.lookup(".thumb");
Label label = new Label();
label.textProperty().bind(timeSlider.valueProperty().asString("%.1f"));
// the following line points to thumb, which is null then… (debugger proof)
thumb.getChildren().add(label);
}
}
In the Main.java
I just load the fxml file:
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("MainView.fxml"));
Parent root = loader.load();
Scene scene = new Scene(root,800,600);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Finally, the fxml file:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<VBox fx:id="root" maxHeight="600" maxWidth="800" prefHeight="600"
prefWidth="800" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="application.MainViewController">
</VBox>