How could I make a slider like this? Could this even be executed as a slider, or do I need another kind of node for this?

82 views Asked by At

The kind of Slider I would want to use:

enter image description here

Is this possible or do I need another kind of Node to execute this? Is this even possible in JavaFX?

I haven't tried anything yet, but it's kind of hard to find information about customizing sliders

2

There are 2 answers

3
James_D On BEST ANSWER

A control that has buttons to increment or decrement a value is a Spinner. The CSS documentation shows how to modify the position of the increment and decrement buttons.

Here is a quick demo:


import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Spinner;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class SpinnerDemo extends Application {
    @Override
    public void start(Stage stage) {
        Spinner<Integer> spinner = new Spinner<>(1, 10, 1);
        spinner.getStyleClass().add("split-arrows-horizontal");
        spinner.valueProperty().addListener((obs, oldValue, newValue) -> System.out.println("Song "+newValue+" selected"));
        spinner.setEditable(false);

        VBox controls = new VBox(5, spinner, new Label("Select Song"));
        controls.setAlignment(Pos.CENTER);

        Scene scene = new Scene(controls, 400 ,400);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

enter image description here

Further styling can be achieved in the usual way with CSS. For example, applying this stylesheet

.spinner.split-arrows-horizontal .text-field {
    -fx-pref-column-count: 5;
}

.spinner,
.spinner .text-field,
.spinner .increment-arrow-button,
.spinner .decrement-arrow-button {
    -fx-background-color: -fx-background;
}


.spinner .increment-arrow-button:hover,
.spinner .decrement-arrow-button:hover {
    -fx-background-color: derive(-fx-background, -3%);
}

.spinner .increment-arrow-button:pressed,
.spinner .decrement-arrow-button:pressed {
    -fx-background: -fx-pressed-base;
}

results in

enter image description here

3
SedJ601 On

I am confused about if you are looking for a Spinner or a Slider. James D posted a Spinner answer. This is a Slider answer.

Altered from here.

mport javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import org.kordamp.ikonli.antdesignicons.AntDesignIconsFilled;
import org.kordamp.ikonli.javafx.FontIcon;

public class App extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        Slider slider = new Slider(1, 10, 3);
        slider.setShowTickMarks(true);
        slider.setShowTickLabels(true);
        slider.setMajorTickUnit(1f);
        slider.setBlockIncrement(1f);
        slider.setSnapToTicks(true);

        
        Text text = new Text();
        FontIcon fiCaretLeft = new FontIcon(AntDesignIconsFilled.CARET_LEFT);
        FontIcon fiCaretRight = new FontIcon(AntDesignIconsFilled.CARET_RIGHT);
        HBox thumbRoot = new HBox(fiCaretLeft, text, fiCaretRight);
        thumbRoot.setAlignment(Pos.CENTER);
        slider.skinProperty().addListener((obs,old,skin)->{
            if(skin!=null){
                StackPane thumb = (StackPane)slider.lookup(".thumb");
                thumb.setPadding(new Insets(10));
                thumb.getChildren().add(thumbRoot);
            }
        });
        slider.valueProperty().addListener((obs,old,val)->text.setText(val.intValue()+""));
        slider.setValue(2);

        VBox root = new VBox(slider);
        root.setAlignment(Pos.CENTER);
        root.setPadding(new Insets(20));
        root.setSpacing(20);
        Scene scene = new Scene(root,600,200);
        primaryStage.setScene(scene);
        primaryStage.setTitle("Slider Text Demo");
        primaryStage.show();
    }
}

enter image description here