Devorious
Devorious

Reputation: 107

JavaFX Change ScrollBar width from a ScrollPane

How can you change the width of a ScrollBar from a ScrollPane to a certain value of px? I looked at JavaFX 2.1 Change ScrollPane Scrollbar size but simply setting the font size to X px doesn't seem to work properly. I did some tests with big values and the width wasn't what I set it to be (ex: for a value of 50px the ScrollBar had width of 56px, for a value of 88px it had width of 96px, for a value of 40px it had width of 44px, for a value of 30px it had width of 33px, so no relation between then).

I need a solution that works from java code and not from a CSS file as I need to be able to dynamically set the value.

There were other suggestions to use .lookupAll but from what I understand you should avoid using that.

Code for setting width and colors:

scrollPane.setStyle("colorScrollBar: rgba(" + A function that returns RBGA + ");"
        + " colorScrollBarButton: rgba(" + A function that returns RBGA + ");" 
        + " -fx-font-size: " + 30 + "px;");

Here is the CSS file I used to change the ScrollBar (to make it transparent, to change the colors and remove some margins):

.scroll-bar {
    -fx-background-color: colorScrollBar;
    -fx-background-insets: 0;
    -fx-padding: 0;
}

.scroll-bar .thumb {
    -fx-background-color: colorScrollBarButton;
}

.scroll-bar > .increment-button > .increment-arrow,
.scroll-bar > .decrement-button > .decrement-arrow {
    -fx-background-color: colorScrollBarButton;
}

.scroll-bar > .increment-button:hover,
.scroll-bar > .decrement-button:hover {
    -fx-background-color: colorScrollBar;
}

.scroll-pane > .viewport {
   -fx-background-color: transparent;
}

.scroll-pane {
    -fx-background-color: transparent;
    -fx-background-insets: 0;
    -fx-padding: 0;
}

.scroll-pane:focused {
    -fx-background-insets: 0;
    -fx-padding: 0;
}

.scroll-pane .corner {
    -fx-background-insets: 0;
    -fx-padding: 0;
}

Upvotes: 0

Views: 914

Answers (4)

vit
vit

Reputation: 67

Been struggling with this problem for some time, found an answer

You can add listener to your scrollPane's children, and set the widths to your scrollBars as they appear:

ScrollPane scrollPane = new ScrollPane(pane);
scrollPane.getChildrenUnmodifiable().addListener(new ListChangeListener<Node>() {
            @Override
            public void onChanged(Change<? extends Node> c) {
                while (c.next()) {
                    if (c.wasAdded()) {
                        c.getAddedSubList().forEach(n -> {
                            if (n instanceof ScrollBar) {
                                ScrollBar bar = (ScrollBar) n;
                                bar.setPrefWidth(30); //set what you need
                            }
                        });
                    }
                }
            }
        });

PS Sorry for necroposting

Upvotes: 0

Oboe
Oboe

Reputation: 2723

Once in the Scene, you can query the ScrollBars using:

ScrollBar vsb = (ScrollBar) scrollPane.queryAccessibleAttribute(
        AccessibleAttribute.VERTICAL_SCROLLBAR);
ScrollBar hsb = (ScrollBar) scrollPane.queryAccessibleAttribute(
        AccessibleAttribute.HORIZONTAL_SCROLLBAR);

vsb.setPrefWidth(40);
hsb.setPrefHeight(40);

Upvotes: 0

swpalmer
swpalmer

Reputation: 4390

This works for me.


    private ScrollPane scrollPane;

    @Override
    public void start(Stage primaryStage) {
        BorderPane root = new BorderPane();

        Circle content = new Circle(2000);
        scrollPane = new ScrollPane(content);
        
        Slider sizeSldr = new Slider(8, 80, 14);
        root.setTop(sizeSldr);
        root.setCenter(scrollPane);

        sizeSldr.valueProperty().addListener((observable,  oldValue,  newValue) -> {
            setScrollBarWidth(newValue.doubleValue());
        });

        Scene scene = new Scene(root, 800, 600);
        primaryStage.setTitle("ScrollBar Width");
        primaryStage.setScene(scene);
        primaryStage.show();
    }


    void setScrollBarWidth(double width) {
        scrollPane.setStyle("-fx-font-size: %3.3fpx".formatted(width));
    }

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

Upvotes: 2

Devorious
Devorious

Reputation: 107

The solution I came with is to create a custom ScrollBar and use that to scroll the ScrollPane. Here is an example how to create one and bind it to the ScrollPane:

ScrollPane scrollPane = new ScrollPane();
scrollPane.setContent(paneElements); //The pane that will have the nodes
scrollPane.setLayoutX(20);
scrollPane.setLayoutY(20);
scrollPane.setPrefWidth(stage.getWidth() - 40); //This was my use case, do what you need here
scrollPane.setPrefHeight(stage.getHeight() - 66); //This was my use case, do what you need here
scrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
scrollPane.setVbarPolicy(ScrollBarPolicy.NEVER);
scrollPane.setStyle("colorScrollBar: rgba(" + I am using a function that returns RGBA + ");"
        + " colorScrollBarButton: rgba(" + I am using a function that returns RGBA + ");");
pane.getChildren().add(scrollPane);

ScrollBar scrollBarVertical = new ScrollBar();
scrollBarVertical.setLayoutX(stage.getWidth() - 20)); //Use what you need
scrollBarVertical.setLayoutY(20); //Use what you need
scrollBarVertical.setPrefHeight(stage.getHeight() - 66); //Use what you need
scrollBarVertical.setMinWidth(0); //I set it to 0 because if you need to use low values, it wasn't using values lower then 16 in prefWidth in my case
scrollBarVertical.setPrefWidth(prefWidth * 0.75)); //Use what you need
scrollBarVertical.setOrientation(Orientation.VERTICAL);
scrollBarVertical.setMin(scrollPane.getVmin());
scrollBarVertical.setMax(scrollPane.getVmax());
scrollBarVertical.valueProperty().bindBidirectional(scrollPane.vvalueProperty());
scrollBarVertical.setStyle("colorScrollBar: rgba(" + I am using a function that returns RGBA + ");"
        + " colorScrollBarButton: rgba(" + I am using a function that returns RGBA + ");");
pane.getChildren().add(scrollBarVertical);

Upvotes: 0

Related Questions