I'm trying to bind a label to be displayed above the lower and upper thumbs of RangeSlider.
The label's position should always remain above their respective thumb, no matter where the user slides it. Like so:
My approach is to attach listeners to each thumb so that I can set the label's to have appropriate X/Y coordinates every time a user slides. But when I run the following code I can't seem to get a reference to the individuals thumbs, via css selectors.
I followed this post, but this only uses one thumb and is therefore easy to reference. How do you properly use CSS selectors in my context, or what is a better approach if mine is flawed?
Controller
public class SliderDemoController implements Initializable {
@FXML
private RangeSlider range;
@Override
public void initialize(URL location, ResourceBundle resources) {
Pane thumb = (Pane) range.lookup(".range-slider .low-thumb");
System.out.println(thumb); // <-- Prints null
}
}
Main
public class SliderDemoMain extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage initStage) throws IOException {
FXMLLoader loader = new FXMLLoader(Drag.class.getClassLoader().getResource("sliderdemo.fxml"));
Parent root = loader.load();
Scene scene = new Scene(root);
Stage primaryStage = new Stage();
primaryStage.setTitle("Slider Demo");
primaryStage.setScene(scene);
primaryStage.show();
}
}
styleMain.css
.range-slider .range-bar {
-fx-background-color: grey;
}
.range-slider .low-thumb {
//....
}
.range-slider .high-thumb {
//....
}
Top Line of sliderdemo.fxml
<HBox fx:id="menuBar" maxHeight="-Infinity" minHeight="-Infinity" prefHeight="79.0" stylesheets="@styleMain.css" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.propertydrop.SliderDemoController">
For CSS lookups to work, you need CSS to have been applied, a layout pass to have been made, and the node to be part of a scene. (Note this in the post you referenced, the code in the answer carefully performs these steps before performing the lookup.)
This is difficult to achieve in a controller, because the
initialize()
method is typically invoked before the root node from the FXML is added to a scene. You can hack this by observing thesceneProperty()
of the node, and responding when it is set to something non-null. (Yes, this is a bit of a hack...):Depending on your exact requirements, you might be able to get away with something a little less ugly, such as performing the lookup in an event handler or a listener on the slider's
highValue
orlowValue
properties.