SDIDSA
SDIDSA

Reputation: 1004

FlowPane automatic horizontal space

I have a FlowPane with equally-sized rectangular children and I have this problem with the space at the right end of the flowpane, when the space is not enough to fit another column of children, I want it to be equally divided between the other columns.

An example of what I want to achieve is how the file explorer in windows behaves, see the gif bellow for reference

preferred behavior

The default FlowPane behaviour doesn't look like this, it leaves the remaining width that can't fit a new child at the end of the region, as shown in the gif bellow

default behavior

And I failed to find any API or documentation to help me achieve my goal, I thought of adding a listener on the width property and adjusting the hGap property accordingly, something like

[ flowPaneWidth - (sum of the widths of the children in one column) ] / (column count - 1)

But again, I have no idea how to figure out the column count, so any help would be appreciated.

Here is a MRE if anyone wants to try their ideas :

public class FPAutoSpace extends Application {
    @Override
    public void start(Stage ps) throws Exception {
        FlowPane root = new FlowPane(10, 10);
        root.setPadding(new Insets(10));
        
        for(int i = 0; i < 20; i++) {           
            root.getChildren().add(new Rectangle(100, 100, Color.GRAY));
        }

        ps.setScene(new Scene(root, 600, 600));
        ps.show();
    }
}

Upvotes: 4

Views: 314

Answers (1)

SDIDSA
SDIDSA

Reputation: 1004

After a bit of thinking, I tried to implement the idea mentioned in the question :

adding a listener on the width property and adjusting the hGap property accordingly

but I added the listener on the needsLayout property instead, as follows :

public class FPAutoSpace extends Application {
    private double nodeWidth = 100;
    @Override
    public void start(Stage ps) throws Exception {
        FlowPane root = new FlowPane();
        root.setVgap(10);

        for (int i = 0; i < 20; i++) {
            root.getChildren().add(new Rectangle(nodeWidth, nodeWidth, Color.GRAY));
        }

        root.needsLayoutProperty().addListener((obs, ov, nv) -> {                   
            int colCount = (int) (root.getWidth() / nodeWidth);
            //added 4 pixels because it gets glitchy otherwise
            double occupiedWidth = nodeWidth * colCount + 4;
            double hGap = (root.getWidth() - occupiedWidth) / (colCount - 1);
            root.setHgap(hGap);
        });

        StackPane preRoot = new StackPane(root);
        preRoot.setPadding(new Insets(10));
        preRoot.setAlignment(Pos.TOP_LEFT);
        ps.setScene(new Scene(preRoot, 600, 600));
        ps.show();
    }
}

Not sure how this will hold up in a multi-hundred node FlowPane but it worked for the MRE

somewhat desired behaviour

Let me know if you think there are better ways to do it.

Upvotes: 3

Related Questions