skip to Main Content

I want to be able to assign a hover color via CSS to a SplitPane Divider in JavaFX.

I am able to achive this by using the following CSS

.split-pane:horizontal > .split-pane-divider {
    -fx-background-color: transparent;
}
.split-pane:horizontal > .split-pane-divider:hover {
    -fx-background-color: lightblue;
}

However: since the divider is lagging behind the cursor, it causes a flickering effect, since the hover is triggered whenever the divider catches up to the cursor position – but while dragging slowly, it’s just a lot of flickering.

I want the hover color to be applied throughout any dragging of the divider.

Is there a way to achieve this via CSS? I tried .split-pane-divider:focused and .split-pane-divider:selected, but no luck 🙁

If not, is there any other way to achieve this?

Thanks!

2

Answers


  1. Chosen as BEST ANSWER

    The solution of Sai Dandem works, but the solution due to the comment of James_D makes it quite a bit simpler. Thanks to both of you!

    For a general split-pane:

    .split-pane > .split-pane-divider {
        -fx-background-color: transparent;
    }
    .split-pane > .split-pane-divider:hover,
    .split-pane > .split-pane-divider:pressed {
        -fx-background-color: lightblue;
    }
    

  2. One way to fix this issue is by including a new pseudo state to the SplitPane (when the divider is in dragging mode). And include that state in the css same as hover state.

    The general idea is to set a custom pseudo state on mouse pressed filter and remove the state on mouse released. Setting the pseudo state on SplitPane will set on the divider as well, so you can set the style specifically for .split-pane-divider:pressed.

    Something like in the below demo:

    enter image description here

    import javafx.application.Application;
    import javafx.css.PseudoClass;
    import javafx.geometry.Insets;
    import javafx.geometry.Orientation;
    import javafx.scene.Scene;
    import javafx.scene.control.SplitPane;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.layout.HBox;
    import javafx.scene.layout.Priority;
    import javafx.scene.layout.StackPane;
    import javafx.stage.Stage;
    
    public class SplitPaneResizeIssueDemo extends Application {
    
        private final PseudoClass PRESSED_PSEUDOCLASS = PseudoClass.getPseudoClass("pressed");
    
        public static final String CSS = "data:text/css," + // language=CSS
                """
                                        .split-pane:vertical > .split-pane-divider {
                                            -fx-background-color: transparent;
                                        }
                                        .split-pane:vertical > .split-pane-divider:hover,
                                        .split-pane:vertical > .split-pane-divider:pressed{
                                            -fx-background-color: lightblue;
                                        }
                        """;
    
        public static void main(final String... a) {
            Application.launch(a);
        }
    
        @Override
        public void start(final Stage primaryStage) throws Exception {
            StackPane root = new StackPane(buildSplitPane());
            final Scene scene = new Scene(root, 300, 400);
            scene.getStylesheets().add(CSS);
            primaryStage.setScene(scene);
            primaryStage.setTitle("SplitPane " + System.getProperty("javafx.runtime.version"));
            primaryStage.show();
        }
    
        private SplitPane buildSplitPane() {
            final SplitPane splitPane = new SplitPane();
            splitPane.setStyle("-fx-background-color:yellow;");
            splitPane.setPadding(new Insets(15));
            splitPane.setOrientation(Orientation.VERTICAL);
            splitPane.setDividerPositions(.60);
    
            splitPane.addEventFilter(MouseEvent.MOUSE_PRESSED, e -> splitPane.pseudoClassStateChanged(PRESSED_PSEUDOCLASS, true));
            splitPane.addEventFilter(MouseEvent.MOUSE_RELEASED, e -> splitPane.pseudoClassStateChanged(PRESSED_PSEUDOCLASS, false));
    
            StackPane top = new StackPane();
            top.setMinSize(100, 10);
            top.setStyle("-fx-border-width:1px;-fx-border-color:black;-fx-border-style:solid;-fx-background-color:white;");
            StackPane bottom = new StackPane();
            bottom.setMinSize(100, 10);
            bottom.setStyle("-fx-border-width:1px;-fx-border-color:black;-fx-border-style:solid;-fx-background-color:white;");
            splitPane.getItems().addAll(top, bottom);
            HBox.setHgrow(splitPane, Priority.ALWAYS);
            return splitPane;
        }
    }
    

    Note: Maybe set a more unique pseudo state name, as pressed is already existing for Button and may conflict if the SplitPane has Button in its children hierarchy.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search