Michael Michael - 13 days ago 6
Java Question

How to add listener to divider position?

Is there a way to add listener whenever I resize my splitpane?

I currently have

split.getDividers().get(0).positionProperty().addListener(new ChangeListener<Number>(){
public void changed(ObservableValue<? extends Number> observableValue, Number oldWindowWidth, Number newWindowWidth){
//code
}
});


which detects whenever the window or divider size is changed, but I only need to know when the divider position is changed, like when I drag it with the mouse. Is there a way to do that? Any help will be appreciated!

Answer

There is no clean way to do this but it is possible for example by using CSS lookup on the SplitPane.

As the dividers has the CSS class of split-pane-divider you can get the dividers from the scene-graph, and they are actually StackPane instances.

On these StackPane you can register a mouse pressed and a mouse release event and update a class member that indicates that the divider is "in a drag" at the moment. And then in the position property listener you can check this class member: if it is true that means that the divider is moved by the mouse, otherwise the change can be ignored.

Example:

public class Main extends Application {

    // Indicates that the divider is currently dragged by the mouse
    private boolean mouseDragOnDivider = false;

    @Override
    public void start(Stage primaryStage) throws Exception{

        SplitPane sp = new SplitPane();

        sp.getItems().addAll(new StackPane(), new StackPane());
        sp.setDividerPositions(0.3f);

        // Listen to the position property
        sp.getDividers().get(0).positionProperty().addListener((obs, oldVal, newVal) -> {
            if(mouseDragOnDivider)
                System.out.println("It's a mouse drag to pos: " + newVal.doubleValue());
        });

        primaryStage.setScene(new Scene(sp, 300, 275));

        sp.requestLayout();
        sp.applyCss();

        // For each divider register a mouse pressed and a released listener
        for(Node node: sp.lookupAll(".split-pane-divider")) {
            node.setOnMousePressed(evMousePressed -> mouseDragOnDivider = true);
            node.setOnMouseReleased(evMouseReleased -> mouseDragOnDivider = false );
        }

        primaryStage.show();
    }


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

Note: As the lookup only works if the layout is done and the CSS is applied, it is important that the requestLayout() and the applyCss() methods are already executed and also that the SplitPane is already added to the scene-graph (attached to a Scene).

Comments