javafxsplitpane

SplitPane dividers synchronization JavaFX


I want to synchronize dividers in SplitPane, when divider(0) moves, I also want to make the same move by divider(1). I guess I have to bind the positionProperty of divider(0) with something.

How can I achieve this?


Solution

  • You need to add listeners to the positions of each divider, and update the "linked" divider when it changes. It's important to make sure you don't end up in an infinite recursive loop; the simplest way to do this is to set a flag indicating your updating, and not propagate the update if it's set.

    Here's a proof-of-concept example that binds two dividers so the portion between them is always 1/3 of the split pane:

    import java.util.List;
    
    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.control.SplitPane;
    import javafx.scene.control.SplitPane.Divider;
    import javafx.scene.layout.Pane;
    import javafx.scene.layout.Region;
    import javafx.stage.Stage;
    
    public class SplitPaneDemo extends Application {
    
        // helper class that binds two divider positions so the portion between them
        // is always 1/3 of the split pane
        private static class DividerPositionBinder {
    
    
            private static final double ONE_THIRD = 1.0/3.0;
            private boolean updating ;
    
            DividerPositionBinder(List<Divider> dividers) {
    
                dividers.get(0).positionProperty().addListener((obs, oldPos, newPos) -> {
                    // don't propagate update if already in an update:
                    if (updating) return ;
                    // special handling for right edge of split pane:
                    if (newPos.doubleValue() > 1.0 - ONE_THIRD) {
                        dividers.get(0).setPosition(1.0 - ONE_THIRD);
                        dividers.get(1).setPosition(1.0);
                        return ;
                    }
                    // make right divider the new value + 1/3:
                    updating = true ;
                    dividers.get(1).setPosition(newPos.doubleValue() + ONE_THIRD);
                    updating = false ;
                });
    
                dividers.get(1).positionProperty().addListener((obs, oldPos, newPos) -> {
                    // don't propagate update if already in an update:
                    if (updating) return ;
                    // special handling for left edge of split pane:
                    if (newPos.doubleValue() < ONE_THIRD) {
                        dividers.get(1).setPosition(ONE_THIRD);
                        dividers.get(0).setPosition(0.0);
                        return ;
                    }
                    // make left divider the new value - 1/3:
                    updating = true ;
                    dividers.get(0).setPosition(newPos.doubleValue() - ONE_THIRD);
                    updating = false ;
                });
    
            }
        }
    
        @Override
        public void start(Stage primaryStage) {
            Region left = new Pane();
            left.setStyle("-fx-background-color: coral; ");
    
            Region middle = new Pane();
            middle.setStyle("-fx-background-color: aquamarine ;");
    
            Region right = new Pane();
            right.setStyle("-fx-background-color: cornflowerblue ;");
    
            SplitPane splitPane = new SplitPane(left, middle, right);
    
            new DividerPositionBinder(splitPane.getDividers());
    
    
            Scene scene = new Scene(splitPane, 800, 800);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
    
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    enter image description here